spring cloud zuul实现限流

发布时间 2023-07-13 22:45:46作者: 天晴修屋顶

上一篇文章《spring cloud zuul实践》介绍了zuul做网关的demo,再扩展一下过滤器就可以实现限流。限流有很多做法,这里介绍令牌实现限流

一、 令牌

通过第三方组件按照固定速率投放令牌到令牌桶里,当令牌桶装满,则不再接收令牌。当请求过来时,先申请拿令牌,拿到令牌则pass请求,并且消耗掉一个令牌,拿不到令牌则拒绝请求,概要流程如下图所示

 

二、在网关zuul中过滤请求时,加入令牌逻辑,从而实现限流

 1 import com.google.common.util.concurrent.RateLimiter;
 2 import com.netflix.zuul.ZuulFilter;
 3 import com.netflix.zuul.context.RequestContext;
 4 import com.netflix.zuul.exception.ZuulException;
 5 import org.springframework.http.HttpStatus;
 6 import org.springframework.stereotype.Component;
 7 
 8 import java.util.concurrent.TimeUnit;
 9 
10 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
11 import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SERVLET_DETECTION_FILTER_ORDER;
12 
13 /**
14  * @Classname RateLimiter
15  * @Created by Michael
16  * @Date 2023/7/13
17  * @Description 限流过滤
18  */
19 @Component
20 public class MyRateLimiter extends ZuulFilter {
21 
22   //  令牌桶
23   static RateLimiter rateLimiter 
24           = RateLimiter.create(8,2, TimeUnit.SECONDS);
25 
26   @Override
27   public String filterType() {
28     return PRE_TYPE;
29   }
30 
31   @Override
32   public int filterOrder() {
33     return SERVLET_DETECTION_FILTER_ORDER -1;
34   }
35 
36   @Override
37   public boolean shouldFilter() {
38     return true;
39   }
40 
41   @Override
42   public Object run() throws ZuulException {
43     RequestContext context = RequestContext.getCurrentContext();
44     boolean allowed = rateLimiter.tryAcquire();
45     if(!allowed){
46       context.setSendZuulResponse(false);
47       context.setResponseStatusCode(501);
48     }
49     return null;
50   }
51 }
MyRateLimiter.java

以上代码中RateLimiter.create(8,2, TimeUnit.SECONDS)

第一个参数,是总令牌数

第二个参数,简单理解每次都放多少个令牌

第三个参数,是时间单位,即多久投放依次令牌

三、测试

每200ms发起一次请求,连续请求15次,可以看到请求结果结果如下: