概念
关于微服务网关Gateway中有几十种过滤工厂,这一篇博文记录的是关于请求限流过滤工厂,也就是标题中的RequestRateLimiterGatewayFilterFactory。这个路由过滤工厂是用来判断当前请求是否应该被处理,如果不会被处理就会返回HTTP状态码为429的code。接下来构建两个模块,其中一个是服务模块,一个是网关模块来测试关于请求过滤工厂是否生效。
服务
引入依赖
XML
<dependencies>
<!-- 由于仅是测试 于是无需多引入微服务相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
修改yml配置
java
server:
port: 8081
spring:
application:
name: cloud-demo
接口路径
java
@RestController
@RequestMapping("/filter")
public class RateLimiterFilterController {
@GetMapping("/requestRateLimiter")
public String requestRateLimiter() {
return "进入了限流方法";
}
}
网关
引入依赖
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 网关 需要注意的是网关中不要引入spring-boot-starter-web 否则启动报错 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<!-- Redis RateLimiter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
修改yml配置
XML
server:
port: 8080
spring:
application:
name: cloud-gateway
redis:
host: IP
port: 端口
password: 密码
cloud:
gateway:
routes:
- id: request-rate-limiter-route
uri: http://127.0.0.1:8081
predicates:
- Path=/filter/requestRateLimiter/**
filters:
# 需要注意的是Redis要在5.x以上才会生效 并且有密码情况下需要配置正确
- name: RequestRateLimiter
args:
# 对应的限流路由判断
key-resolver: "#{@userKeyResolver}"
# 每秒生成的令牌数
redis-rate-limiter.replenishRate: 2
# 高并发情况下将每秒生成的令牌数增加的个数 即 replenishRate + burstCapacity
redis-rate-limiter.burstCapacity: 2
# 每个请求消耗的令牌个数
redis-rate-limiter.requestedTokens: 2
接口
java
@Configuration
public class FilterConfig {
@Bean
public KeyResolver userKeyResolver() {
// getFirst()是获取MultiValueMap中的第一个key中的值 因为这个MultiValueMap不会产生key冲突导致value覆盖的问题
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
}
测试
当然,既然这个过滤工厂需要配置Redis,那么就一定会需要在Redis中存储数据。打开Redis可视化工具可以发现,因为我没有指定存储的库,所以默认在0数据库中,会被存储两个值。
一个为request_rate_limiter.(user名称).timestamp,另一个为request_rate_limiter.(user名称).tokens。这之后就是涉及到源码的阅读,本篇博文并不会介绍源码,但后续会更新自定义路由过滤工厂。