spring cloud zuul实现限流
上一篇文章《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 }
以上代码中RateLimiter.create(8,2, TimeUnit.SECONDS)
第一个参数,是总令牌数
第二个参数,简单理解为多久放令牌
第三个参数,是时间单位,即多久投放依次令牌
三、测试
每200ms发起一次请求,连续请求15次,可以看到请求结果结果如下:
如果该文章对你有所帮助,请点个赞支持下,谢谢!