springcloud實現限流


在高並發中,限流是必不可少的一個環節,如何使用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;
    }
}
復制代碼

 

編寫測試類,模仿http請求訪問某個服務。

復制代碼
public class HttpRequest {
    public static void main(String[] args)throws Exception {
        Thread []thread = new Thread[10];
        for(int i = 0;i < 10;i++){
            thread[i] = new Thread(()->{
                try{
                    URI url = new URI("http://localhost:9527/menbbo/springcloudzuul/index");
                    SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
                    ClientHttpRequest request = simpleClientHttpRequestFactory.createRequest(url, HttpMethod.POST);
                    ClientHttpResponse execute = request.execute();
                    InputStream body = execute.getBody();
                    InputStreamReader ins =  new InputStreamReader(body);
                    BufferedReader bufferedReader = new BufferedReader(ins);
                    String s = "";
                    while ((s=bufferedReader.readLine())!=null){
                        System.out.println(s);
                    }
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            });
        }
        for(int i =0;i<10;i++){
            thread[i].start();
        }
    }
}
復制代碼

結果如下:

 

 調用成功3次,其他被過濾掉。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM