Resilience中的RateLimiter
- 一、RateLimiter(限流)
- 1.常见的限流算法
- 漏桶算法(Leaky Bucket)
- 令牌桶算法(Token Bucket)——Spring cloud 默认使用该算法
- 滚动时间窗口(tumbling time window)
- 滑动时间窗口(sliding time window)
- 2.实际应用
一、RateLimiter(限流)
限流
就是限制最大访问流量
。系统能提供的最大并发是有限的,同时来的请求又太多,就需要限流
。- 比如商城秒杀业务,瞬时大量请求涌入,服务器忙不过来就只好排队限流了,和去景点排队买票、去银行办理业务排队等号道理相同。
- 所谓限流,就是通过对并发访问/请求进行限速,或者对一个时间窗口内的请求进行限速,以保护应用系统,一旦达到限制速率则可以
拒绝服务
、排队等待
或降级
等处理。
1.常见的限流算法
漏桶算法(Leaky Bucket)
- 一个固定容量的漏桶,按照设定常量固定速率流出水滴,类似医院打吊针,不管你源头流量多大,我按照设定匀速流出。
- 如果流入水滴超出了桶的容量,则流入的水滴将会溢出(被丢弃),而漏桶容量是不变的。
- 这里有两个变量,一个是桶的大小,支持流量突发(Burst)增多时可以存储多少,另一个是水桶漏洞的大小(Rate)。因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞)<- - - 没懂,漏桶算法也不能使流速突发(Burst)到流入速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。为了更好的控制流量,漏桶算法需要通过对上面的两个变量进行控制。
- 那为什么我最开始不能把桶的漏口尽可能的设置的大呢?<- - - 疑问
令牌桶算法(Token Bucket)——Spring cloud 默认使用该算法
滚动时间窗口(tumbling time window)
滑动时间窗口(sliding time window)
2.实际应用
编写具体的提供服务接口
/**
* Resilience4j rateLimit 的例子
* @param id 主键
* @return 返回结果
*/
@GetMapping("/pay/rateLimit/{id}")
public String myRateLimit(@PathVariable("id") Integer id) {
return "Hello, myRateLimit 欢迎到来 inputId: "+ id + "\t" + UUID.randomUUID();
}
如果使用了 openfeign 需要将提供服务的接口注册到对外暴露的接口中
/**
* Resilience4j rateLimit 的例子
* @param id 主键
* @return 返回结果
*/
@GetMapping("/pay/rateLimit/{id}")
String myRateLimit(@PathVariable("id") Integer id);
在调用服务方引入 ratelimiter 相关的依赖
<!--resilience4j-rateLimiter-->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-ratelimiter</artifactId>
</dependency>
<!--circuitBreaker-resilience4j-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!--circuitBreaker 是基于AOP实现的 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
在调用服务方添加 rateLimiter 相关的配置项(仅仅是 rateLimiter 相关的配置,其他配置根据自己的情况)
#=================resilience4j ratelimiter 限流的配置
resilience4j:
ratelimiter:
configs:
default:
limit-for-period: 2 # 在一次刷新周期内,允许执行的最大请求数
limit-refresh-period: 5s # 限流器每隔 limit-refresh-period 刷新一次,将允许处理的最大请求数量重置为 limit-for-period
timeout-duration: 1 # 线程等待权限的默认等待时间。
instances:
cloud-payment-service:
base-config: default
编写调用方相关的接口
@GetMapping("/pay/rateLimit/{id}")
@RateLimiter(name = "cloud-payment-service", fallbackMethod = "myRateLimitFallback")
public String myRateLimit(@PathVariable("id") Integer id) {
return payFeignApi.myRateLimit(id);
}
public String myRateLimitFallback(Integer id, Throwable t){
return "你被限流了,禁止访问!!! input: " + id;
}