本文介绍一个Spring Cloud Gateway 的请求限流配置,使用 Redis 实现令牌桶算法。
一、YAML 配置解析
application.ymlspring:cloud:gateway:routes:-id:user-serviceuri:lb://user-servicepredicates:-Path=/api/users/**filters:-name:RequestRateLimiterargs:redis-rate-limiter.replenishRate:10# 每秒10个redis-rate-limiter.burstCapacity:20# 突发20个key-resolver:"#{@userKeyResolver}"# 按用户限流1. 路由配置
routes:-id:user-serviceuri:lb://user-service# 目标服务(负载均衡)predicates:-Path=/api/users/**# 匹配的路径filters:-name:RequestRateLimiter# 启用限流过滤器2. 限流参数
args:redis-rate-limiter.replenishRate:10# 令牌生成速率:10个/秒redis-rate-limiter.burstCapacity:20# 令牌桶容量:20个key-resolver:"#{@userKeyResolver}"# 限流维度:按用户令牌桶算法原理:
- 系统以固定速率(10个/秒)生成令牌放入桶中
- 桶最多存放20个令牌(应对突发流量)
- 请求到达时,从桶中取一个令牌
- 如果桶空,则拒绝请求(429 Too Many Requests)
二、Java 配置解析
@ConfigurationpublicclassRateLimitConfig{@BeanpublicKeyResolveruserKeyResolver(){returnexchange->{// 按用户ID限流StringuserId=exchange.getRequest().getHeaders().getFirst("X-User-ID");returnMono.just(userId!=null?userId:"anonymous");};}@BeanpublicKeyResolverapiKeyResolver(){returnexchange->{// 按API路径限流Stringpath=exchange.getRequest().getPath().value();returnMono.just(path);};}}1. KeyResolver Bean
@BeanpublicKeyResolveruserKeyResolver(){returnexchange->{StringuserId=exchange.getRequest().getHeaders().getFirst("X-User-ID");returnMono.just(userId!=null?userId:"anonymous");};}作用:根据请求头中的X-User-ID区分不同用户进行限流。如果未提供,则归为 “anonymous” 用户组。
2. 另一个备用解析器
@BeanpublicKeyResolverapiKeyResolver(){returnexchange->{Stringpath=exchange.getRequest().getPath().value();returnMono.just(path);// 按API路径限流};}说明:这个解析器可以用于按API路径限流,但当前配置使用的是userKeyResolver。
三、工作流程
请求流程: 1. 用户访问 /api/users/123 2. Gateway 提取 X-User-ID 头(如 "user-001") 3. 检查 Redis 中 "user-001" 的令牌桶 4. 如果有令牌 → 转发到 user-service 5. 如果无令牌 → 返回 429 错误四、限流效果示例
假设有3个用户:
- 用户A(
X-User-ID: user1):频繁访问 - 用户B(
X-User-ID: user2):偶尔访问 - 匿名用户:未传 X-User-ID
结果:
- 每个用户独立限流(每秒最多10个请求)
- 用户之间互不影响
- 突发流量最多支持20个请求(超过后按10个/秒匀速处理)
五、Redis 数据结构
Gateway 会在 Redis 中创建键值对:
request_rate_limiter.{userId}.tokens # 剩余令牌数 request_rate_limiter.{userId}.timestamp # 最后更新时间六、实际应用场景
- 防止恶意请求:限制单个用户频繁调用
- 保护后端服务:避免突发流量打垮服务
- 公平使用:确保每个用户都有机会访问
- 分级限流:可通过配置不同限流规则实现VIP/普通用户区别对待
七、自定义扩展
可以修改KeyResolver实现更复杂的限流策略:
- 按IP地址限流
- 按用户等级动态调整限流阈值
- 结合时间段的动态限流
- 白名单用户不限流