成功:SpringCloud Gateway限流_RateLimiter_RedisRateLimiter
文章目录配置yaml依赖Java执行故障不起效原因配置yaml看注释spring:cloud:gateway:routes:- id: requestratelimiter_route # 过滤器名称,不必在意uri: https://example.org # 上游,有的地方叫下游-_-||predicates:- Path=/xxx/**filters:-
·
文件名称 | 版本号 | 作者 | 版本 | |
---|---|---|---|---|
成功:SpringCloud Gateway限流_RateLimiter_RedisRateLimiter | v0.0.1 | 学生宫布 | 8416837 | SpringBoot 2.2.6 SpringCloud Gateway 2.2.2 |
配置
yaml
- 注意看注释
- 反面教材
[错误的配置],id不对,应该配置在id是微服务的配置大项下面
。这样不会起效,按下文修正后,起效了。
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route # 过滤器名称,不必在意
uri: https://example.org # 上游,有的地方叫下游-_-||
predicates:
- Path=/xxx/**
filters:
- StripPrefix=1
- name: RequestRateLimiter # 官方给的名称,对应Java类,有需要再改
args:
redis-rate-limiter.replenishRate: 10 # 每秒补充10个
redis-rate-limiter.burstCapacity: 20 # 突发20个
redis-rate-limiter.requestedTokens: 1 # 每次请求消耗1个
# rate-limiter: "#{@redisRateLimiter}" # 限流器
key-resolver: "#{@userAPIKeyResolver}" # 限流key|字段解析器
-
正确的
:
...
# 系统模块
- id: abc-system
uri: lb://abc-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 2
key-resolver: "#{@userAPIKeyResolver}"
# key-resolver: "#{@ipKeyResolver}"
依赖
- xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
<!-- 版本号可以继承父项目或自己写 RELEASE表示最新版-->
<version>RELEASE</version>
</dependency>
Java
标识
- user结合API 限流成功
前提是QueryParams携带user参数(一般不会这么做),否则报空指针错误
// 根据什么字段限流,甚至是组合字段
@Bean
public KeyResolver userAPIKeyResolver() {
// rt,根据字段限流,下文根据Query参数值作为限流标识,请酌情更改为自己的方式
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
// todo 获取消费者消费的API的id,与user组合
}
- ip 限流成功 响应码429 服务降级 拒绝服务
/**
* 功能描述: 基于ip限流
*
* @param: []
* @return: org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
* @qq: 8416837
* @author: cc
* @date: 2020/6/10 11:56
*/
@Bean("ipKeyResolver")
public KeyResolver ipKeyResolver() {
System.out.println("限流解析器");
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
- 限流器 Redis限流器(可以省去,可以使用上文的yaml配置代替)
@Bean
RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(9, 16); // yaml配置文件已经有了,那么这里就省了。9,16对应replenishRate、burstCapacity
}
- 其它key限流
原理一样,使用设置的key存储redis令牌,调用的时候消耗令牌,单位时间内的令牌耗尽则拒绝服务,另外还有个突发流量功能,当突发的时候,令牌会增加,见配置
burstCapacity
。
执行
将配置拷贝到项目或配置中心、代码拷贝到项目,并修改Java代码:KeyResolver
启动项目,使用压测工具压测或者手动发送Http请求,进行测试。
故障
不起效
- 多线程调用接口,每秒发送10个请求,仍然成功了:
分析原因
- 限流过滤器没有拦截到请求
- 可能与路由配置有关,回顾路由配置:
...
# 限流
- id: requestratelimiter_route # 过滤器名称,不必在意
uri: lb://abc-system # 上游,有的地方叫下游-_-||
predicates:
- Path=/system/**
filters:
- name: RequestRateLimiter # 官方给的名称,对应Java类,有需要再改
args:
...
- requestratelimiter_route名称是按照官方的,应该没问题;
- uri表示路由的目标是它,也没问题吧;
- predicates断言是Path类型,是个正则,当正则匹配访问路径时,即将请求指向目标,好像也没问题;
- RequestRateLimiter ,没有找到这个类,但是好像找到了相关Bean:
解决方案
1)增加public,KeyResolver userAPIKeyResolver() {
改为public KeyResolver userAPIKeyResolver() {
2)限流配置改正确
# 系统模块
- id: abc-system
uri: lb://abc-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 2
key-resolver: "#{@userAPIKeyResolver}"
限流成功
根据配置进行限流:
调用接口,限流开始工作,日志
上图使用多线程模拟10个并发,只有2个请求成功,剩余请求返回429(Too Many Request
),说明限流已经ok了,更多细节可以继续优化。
更多推荐
已为社区贡献1条内容
所有评论(0)