Zuul 网关限流---Guava RateLimiter

限流算法有漏桶算法和令牌桶算法,guava的RateLimiter使用的是令牌桶算法也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或者取不到立即返回失败


image

Guava RateLimiter 使用

/**
 * @author haopeng
 * @date 2019-07-16 20:17
 */
public class GuavaRateLimiterTest {

    @Test
    public void testAcquire() {
        // acquire(i); 获取令牌,返回阻塞的时间,支持预消费.
        RateLimiter limiter = RateLimiter.create(100);

        for (int i = 1; i < 20; i++) {
            double waitTime = limiter.acquire();
            System.out.println("cutTime=" + longToDate(System.currentTimeMillis()) + " acq:" + i + " waitTime:" + waitTime);
        }
    }

    public static String longToDate(long lo){
        Date date = new Date(lo);
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sd.format(date);
    }


}

每秒1个令牌生成一个令牌,从输出可看出很平滑,这种实现将突发请求速率平均成固定请求速率。

Zuul中使用

@Component
public class RateLimitFilter extends ZuulFilter {

    private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return SERVLET_DETECTION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        // 如果获取不到令牌,进行拦截
        if (!RATE_LIMITER.tryAcquire()) {
            requestContext.setSendZuulResponse(false);
            HttpStatus.TOO_MANY_REQUESTS.value()
            requestContext.setResponseStatusCode(HttpStatus.BAD_REQUEST.value());
        }
        return null;
    }
}

你可能感兴趣的:(Zuul 网关限流---Guava RateLimiter)