menbbo

导航

 

在高并发中,限流是必不可少的一个环节,如何使用springcloud-zuul实现限流,限流的实现最重要在于算法,常见的限流算法包

括了漏桶算法及令牌桶算法。

漏桶算法

漏桶这个名字就很形象,算法内部有一个容器,类似于漏斗。进来的请求类似于加水,不管倒入的水流量多大,下面出去的水流量很稳定。

不管服务调用方多么不稳定,通过漏桶算法进行限流,每隔固定的时间处理一次请求。因为处理请求的速率固定,所以新加入的请求会被放

置在桶中,等待下一次请求处理,若桶已经放满,则丢弃要加入的请求。

 

 令牌桶算法

令牌桶算法中,有一个桶,算法按照一定的速率向桶中添加令牌,拿到了令牌的请求才能被处理。若请求没有拿到令牌则等待可用的令牌,或者

直接拒绝。若桶中令牌数量达到了上线,就丢弃令牌。

 

 springcloudGateWay实现限流

GoogleGuava提供了限流工具类RateLimiter,如下编写一个pre类型的filter,适用于单zuul节点的情况。

import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;

@Component
public class RateLimitZuulFilter extends ZuulFilter {
    //同一時刻允許請求的個數 3個
    private RateLimiter rateLimiter = RateLimiter.create(2);
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public boolean shouldFilter() {
        //可以考慮弄個開關
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        if(!rateLimiter.tryAcquire()){//超过设置的请求个数
            HttpStatus tooManyRequests = HttpStatus.TOO_MANY_REQUESTS;
            response.setContentType(MediaType.TEXT_PLAIN_VALUE);
            response.setStatus(tooManyRequests.value());
            requestContext.setSendZuulResponse(false);
            throw new ZuulException(tooManyRequests.getReasonPhrase(),tooManyRequests.value(),tooManyRequests.getReasonPhrase());
        }
        return null;
    }
}

 

使用压测工具进行测试:

结果如下:

 

 调用成功3次,其他被过滤掉。

源码地址:https://gitee.com/menbbo/springclouddemo.git

posted on 2020-10-26 22:58  menbbo  阅读(969)  评论(0编辑  收藏  举报