Spring Cloud中Sentinel+Redis限流降级的核心是规则真正生效于网关入口且降级在故障传播前切断调用;关键包括:GatewayFlowRule配置、KeyResolver动态提取限流Key、Redis滑动窗口防跳跃、多实例分桶、降级规则匹配真实失败场景、fallback不抛异常、规则持久化至Redis并正确加载。

Spring Cloud 中用 Sentinel + Redis 做限流降级,核心不是“能不能配通”,而是“限流规则是否真正生效在网关入口、降级逻辑是否在故障传播前就切断调用”。很多项目配完发现压测时流量照样打穿下游,问题往往出在规则作用域、数据源同步、或 fallback 被绕过。
限流必须落在 Spring Cloud Gateway 的 GlobalFilter 层
很多人把 @SentinelResource 加在后端微服务的 Controller 上,这只能保护单个服务,对网关层无效。网关限流必须通过 GatewayFlowRule 配置,并注册到 GatewayRuleManager,否则请求在路由前就已穿过 Sentinel 检查点。
- 确保引入
spring-cloud-alibaba-sentinel-gateway依赖,而非仅spring-cloud-starter-alibaba-sentinel -
application.yml中需显式开启:spring.cloud.sentinel.filter.enabled=true - 限流 Key 必须由
KeyResolver动态提取,例如按request.getRemoteAddress()或request.getQueryParams().get("app_id"),不能写死为常量 - 若使用 Redis 存储计数,
sentinel-datasource-redis必须配置为GatewayRuleManager的数据源,否则控制台修改的规则不会同步到网关实例
Redis 限流计数器要防窗口跳跃和并发覆盖
直接用 INCR + EXPIRE 实现固定窗口,会在窗口切换瞬间允许两倍流量(比如 00:59:59 和 01:00:00 各来 1000 请求)。Sentinel 默认用 Lua 脚本封装滑动窗口逻辑,但前提是 Redis 数据源必须启用且脚本能正确加载。
- 检查
RedisDataSource初始化日志中是否有load flow rule script success - 避免多个网关实例共用一个
key(如全用sentinel:flow:default),应带实例标识或按 routeId 分桶,否则计数互相干扰 - 若用自定义 Lua 脚本,注意
TIME命令返回的是秒+微秒,而 Java 客户端传入的period单位是秒,需统一为毫秒再比对 - 生产环境 Redis 连接池
max-active至少设为 20,低于 8 时高并发下EVAL可能超时,导致限流退化为“不生效”
降级规则必须匹配真实失败场景,且 fallback 不可抛异常
熔断降级不是“只要 QPS 超了就降”,而是基于慢调用比例或异常比例触发。如果下游服务只是响应变慢(如从 50ms 拖到 800ms),但没抛 RuntimeException,默认的异常比例规则根本不会熔断。
- 在
application.yml中配置降级规则时,slowRatioThreshold应设为 0.5(即 50% 请求慢于statIntervalMs),并确保minRequestAmount≥ 5,避免冷启动误判 -
@SentinelResource(fallback = "fallbackHandler")的fallbackHandler方法签名必须与原方法一致,且不能抛出检查异常(如IOException),否则会跳过 fallback 直接向上抛 - 网关层降级建议返回
ResponseEntity.status(429).body("服务繁忙"),而不是重定向或空响应,避免客户端重试加重压力 - 若用 Feign 调用下游,需额外配置
feign.sentinel.enabled=true,否则 Feign 接口的异常不会被 Sentinel 统计
最容易被忽略的一点:Sentinel 控制台配置的规则默认只存在内存,重启网关就丢失。哪怕用了 Redis 数据源,也得确认 redis:// 地址连通、rule-type 设置为 gw-flow(网关流控)或 degrade(降级),否则规则写进去了,网关根本不去读。











