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