SpringCloudGateway限流的实现
spring-cloud-gateway提供了内置的基于Redis,实现令牌桶算法的限流器。
1、默认限流的配置
在spring-cloud-gateway的系列文章的第一篇中,我们介绍了搭建最小化可用的gateway。本篇文章及后续文章我们都会基于以前的基础继续搭建。最小化可用的spring-cloud-gateway
1.1、引入相应jar包
在pom.xml引入redis相关的jar包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
1.2、配置相应接口的限流策略
spring:
cloud:
gateway:
routes:
- id: test
uri: lb://TEST #基于DiscoverClient实现的服务发现路由,转发到TEST服务
order: 0
predicates:
- Path=/test/** # 将test开头的url path路由
filters:
- RewritePath=/test/(?<segment>.*), /$\{
segment} #转发后的请求去除服务名前缀
- name: RequestRateLimiter # cloud-gateway默认的限流器
args:
key-resolver: '#{@hostAddrKeyResolver}' # 限流器可配置的KeyResolver
redis-rate-limiter.replenishRate: 1 # 令牌桶算法的填充速率,1个/s
redis-rate-limiter.requestedTokens: 1 # 令牌桶算法的每个请求消耗的token数,1个/次
redis-rate-limiter.burstCapacity: 1 # 令牌桶算法的容量,1个
redis: # 此处我试用了一下集群,暂时达不到限流的效果,在源码分析里面我们一起来看看原因吧。此处还是有坑的。
host: 10.2.2.63 # redis的host
port: 6379 # redis的port
1.3、实现自定义的KeyResolver
// 我们可以按需是实现多种不同的KeyResover,从而实现不同的限流策略。这算是Cloud-gateway留给我们的一个扩展点
public class HostAddrKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
//将HostAddrKeyResolver注册到Spring容器
@Bean
public HostAddrKeyResolver hostAddrKeyResolver() {
return new HostAddrKeyResolver();
}
通过上面的配置,我们一个简单的限流器就配置好了,当请求频率超过限制后,客户端就会收到429的错误。
通过实现配置KeyResolver,我们可以实现多种限流策略,例如按用户限流,按ip限流, 按url限流,还能够做到各种组合限流。
2、默认限流的源码介绍
spring-cloud-gateway通过RoutePredicateHandlerMapping处理路由转发和断言,每个路由Route都有AsyncPredicate和一个List。我们RedisRateLimiter就是通过RequestRateLimiterGatewayFilterFactory来实现的。核心代码在RequestRateLimiterGatewayFilterFactory中,如下所示:
public GatewayFilter apply(