1. 程式人生 > >關於Guava中令牌桶演算法RateLimiter的理解

關於Guava中令牌桶演算法RateLimiter的理解

      我們系統現在架構是收到mq訊息,先放到redis佇列,然後再從redis佇列取任務去消費,當上遊刷資料的時候,redis佇列任務就會非常多,這個時候我們在消費的時候既要考慮redis的穩定性,也要考慮呼叫下游資源所能提供資源能力。對於資源受限、處理能力不是很強的資源應當給予保護(在下游資源無法或者短時間內無法提升處理效能的情況下)。可以使用限流器或者類似保護機制,避免下游服務崩潰造成整體服務的不可用。這是我們用到了Guava的令牌桶演算法RateLimiter

RateLimiter類似於JDK的訊號量Semphore,他用來限制對資源併發訪問的執行緒數

    RateLimiter limiter = RateLimiter.create(10); //每秒不超過10個任務被提交
        limiter.acquire();  //請求RateLimiter, 超過10個會被阻塞
        executor.submit(runnable); //提交任務

也可以以非阻塞的形式來使用:
If(limiter.tryAcquire()){ //未請求到limiter則立即返回false
    doSomething();
}else{
    doSomethingElse();
}

下面可以看程式碼測試,通過例子就能理解出原理

    public static void main(String args[]){
        //5000當前程式耗時:2007ms
        //40000當前程式耗時:259ms
        //不加速率當前程式耗時:2ms 如果不限速相當於2毫秒就能處理完,
        long startTime=System.currentTimeMillis();
        /**
         * 每秒的令牌數是10000
         * 限速後根據大小,設定的令牌越小,處理速度越慢,設定的令牌數越大,速度越快
         */
        RateLimiter  rateLimiter = RateLimiter.create(40000);
       //rateLimiter.setRate(40000);
        //下面是一些測試程式碼
        for(int i=0;i<10000;i++){
            rateLimiter.acquire();
        }
        long endTime=System.currentTimeMillis();
        System.out.println("當前程式耗時:"+(endTime-startTime)+"ms");
    }

下面是介紹RateLimiter的部落格

http://ifeve.com/guava-ratelimiter/

http://blog.csdn.net/cloud_ll/article/details/43602325

http://www.voidcn.com/blog/jiesa/article/p-4943128.html

http://www.jianshu.com/p/3dfae5c15eb9