Gateway 限流:RequestRateLimiter 与 Redis 实现
网关是所有流量的必经之路,天然适合做限流:把超出的请求挡在服务入口之外,保护后端不被突增流量冲垮。Spring Cloud Gateway 内置的 RequestRateLimiter 过滤器基于令牌桶算法,配合 Redis 实现分布式计数,是官方主推的方案。
为什么计数器放在 Redis
网关通常会多实例部署,若每个实例各自计数,限流总量会变成"实例数 × 单机限额",形同虚设。把令牌桶的状态放到 Redis,所有实例读写同一份计数,才能做到全局准确。Redis 的 Lua 脚本保证了"取令牌"操作的原子性,这是该方案可靠的前提。
令牌桶语义速记
令牌桶有两个参数:replenishRate 表示每秒向桶里补充的令牌数,决定长期平均速率;burstCapacity 表示桶容量,决定瞬间允许的突发量。每次请求消耗 requestedTokens(默认 1)个令牌,桶空了请求就被拒绝。直观理解:replenishRate=10、burstCapacity=20 表示平均每秒 10 个请求,但允许瞬间最多 20 个并发突发。
准备依赖与 Redis
网关工程引入反应式 Redis 依赖,并保证 Redis 可用:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
spring:
data:
redis:
host: localhost
port: 6379
# 若 Redis 同时被其他 Spring Data 功能使用,官方建议关闭 repositories 自动装配
# repositories:
# enabled: false
声明限流过滤器
在目标路由上挂 RequestRateLimiter,key-resolver 指向一个限流维度 Bean(见下):
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒补充令牌
redis-rate-limiter.burstCapacity: 20 # 桶容量
redis-rate-limiter.requestedTokens: 1 # 每请求消耗
key-resolver: "#{@ipKeyResolver}" # 限流维度
定义限流维度:KeyResolver
按什么粒度限流取决于业务:按客户端 IP、按登录用户、按接口都行。KeyResolver 把请求映射成一个限流 key:
@Bean
KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
按 IP 限流能防单点刷量,但多级代理后 IP 可能不可靠(需正确取 X-Forwarded-For);按用户限流更贴近业务(如每个用户每秒最多 N 次),登录场景优先;也可以按"IP + 用户"组合。key 的维度决定规则颗粒度,也决定 Redis 里 key 的数量,注意不要设计出无界增长的 key。
行为与排障
超过限额的请求会被网关直接拒绝并返回 429(Too Many Requests),业务方应捕获该状态做"稍后重试"提示。常见问题:一是忘记引入 reactive Redis 依赖,启动报找不到 RedisRateLimiter 相关 Bean;二是 key-resolver 名字写错,限流不生效或抛异常;三是只配了 replenishRate 没配 burstCapacity(burst 不配置时默认等于 replenish 值,官方文档有说明);四是限流 key 为 null 时会被当作非法请求处理。
与 Sentinel 网关限流的取舍
RequestRateLimiter 适合"网关统一按 Redis 做速率限制"的朴素场景。若需要更丰富的规则(按调用方、动态规则下发、与熔断联动),可在网关上集成 Sentinel 的网关适配模块,二者选型对比以官方文档为准。本教程后续 Sentinel 章节面向服务侧限流,概念可以互通。
小结
限流三件套:令牌桶参数定速率、KeyResolver 定维度、Redis 保全局一致。把"每秒多少请求、突发多少、按谁计数"三个问题回答清楚,配置就完成了。下一部分离开流量入口,转向配置中心,让"改配置不重启"成为可能。