在 Spring Cloud Gateway 中使用自带的 RedisRateLimiter 实现限流
原创2025/8/9大约 2 分钟
在 Spring Cloud Gateway 中使用自带的 RedisRateLimiter 实现限流
1、介绍
在 Spring Cloud Gateway 中,RequestRateLimiterGatewayFilterFactory 工厂类使用一个 RateLimter 实现来判断请求是否被允许继续处理。如果不允许,则会响应 HTTP 429 - Too Many Requests。 网关中自带了一个限流实现类——RedisRateLimiter,它基于 Redis 存储,使用的是令牌桶算法。
2、使用
2.1、添加依赖
在网关项目中添加以下依赖:
<!-- 使用基于响应式的编程模型,符合 Spring Cloud Gateway的响应式架构 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>2.2、自定义限流的Key
实际上,限流计算是通过 KeyResolver 接口来生成键值的,默认实现方式是 PrincipalNameKeyResolver,即基于用户身份认证(前提是有身份认证机制如 OAuth2、jwt 等)来实现限流,若用户未登录,则使用匿名(anonymous)键。
大多数情况下,我们都需要根据自身的业务场景来自定义实现,如下:
@Configuration
public class RequestRateLimiterConfig {
@Bean
@Primary
KeyResolver urlKeyResolver() {
// 按URL限流
return exchange -> {
String key = exchange.getRequest().getPath().toString();
if (StringUtils.isEmpty(key)) {
return Mono.empty();
}
return Mono.just(key);
};
}
@Bean
KeyResolver userKeyResolver() {
// 按用户限流,仅做演示,获取用户信息以实际业务为准
return exchange -> {
String key = exchange.getRequest().getHeaders().getFirst("Authorization");
if (StringUtils.isEmpty(key)) {
return Mono.empty();
}
return Mono.just(key);
};
}
@Bean
KeyResolver ipKeyResolver() {
// 按IP来限流,仅做演示,获取IP地址以实际业务为准
return exchange -> {
String key = exchange.getRequest().getRemoteAddress().getHostName();
if (StringUtils.isEmpty(key)) {
return Mono.empty();
}
return Mono.just(key);
};
}
}2.3、在路由中配置指定的限流Key
设置 redis 连接信息的配置略。
spring:
cloud:
gateway:
routes:
- id: app-service
uri: lb://app-service
predicates:
- Path=/app/**
filters:
- name: RequestRateLimiter
args:
# 令牌桶填充的速率,每秒可以执行多少个请求
redis-rate-limiter.replenishRate: 5
# 令牌桶容量,允许突发请求数,为0则会拒绝所有请求
redis-rate-limiter.burstCapacity: 10
# 每次请求需要消耗多少个令牌,默认为1
redis-rate-limiter.requestedTokens: 1
# 按照IP进行限流,与上面定义的bean名称一致
key-resolver: "#{@ipKeyResolver}"
