關於Guava中令牌桶演算法RateLimiter的理解
阿新 • • 發佈:2019-01-07
我們系統現在架構是收到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