本文将使用以下两种方式实现网关的限流:
- 使用 Spring Cloud Gateway 的
RequestRateLimiter
过滤器工厂基于 Redis
的限流,
- 使用 Sentinel 结合 Spring Cloud Gateway 来实现网关限流。
使用 RequestRateLimiter 过滤器工厂结合 Redis 实现网关限流
RequestRateLimiter
GatewayFilter
工厂使用实现 RateLimiter 的限流器来确定当前请求是否被限流。如果被限流了,则默认返回 HTTP 429 - Too Many Requests
状态。
RequestRateLimiter
网关过滤器工厂采用可选的 keyResolver
参数和特定于速率限制器的参数。
KeyResolver在源码中的定义:
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
复制代码
我们可以通过 KeyResolver 来指定限流的 key
,比如可以根据用户做限流,也可以根据 IP 来做限流,或者根据接口进行限流。
基于 Redis 的限流器
目前限流器的实现提供了基于 Redis 的实现,其使用的算法是 令牌桶算法 。
基于 Redis 的限流,需要引入 spring-boot-starter-data-redis-reactive
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
复制代码
要实现限流,需要配置 Redis 连接以及在配置网关路由的时候添加 RequestRateLimiter
过滤器:
spring:
redis:
host: 192.168.242.112
port: 16397
password: s1lcA6;.7Lx9,x
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"
复制代码
这里配置的是按照用户限流,其中参数 key-resolver: "#{@userKeyResolver}"
是一个 KeyResolver Bean:
@Configuration
public class RateLimiterConfig {
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("userId")));
}
}
复制代码
#{@userKeyResolve