喬木人 的 技術專欄
阿新 • • 發佈:2019-02-08
原理介紹
Leaky Bucket 與 Token Bucket 演算法
實現方式
1. 簡單實現,無burst控制
public enum APIRateLimiter { long minIntervalMilis; private AtomicLong lastRequestTime = new AtomicLong(0); public boolean acquire() { int maxAttempts = 5; while (maxAttempts-- > 0) { long lastRequestMils = lastRequestTime.longValue(); long awaitTime = minIntervalMilis - (System.currentTimeMillis() - lastRequestMils); if (awaitTime > 0) { try { //Log.out("sleep %s mili seconds to aquire lease ...", awaitTime); Thread.sleep(awaitTime); } catch (InterruptedException e) { } } else { if (lastRequestTime.compareAndSet(lastRequestMils, System.currentTimeMillis())) { return true; } } } return false; } }
2. 有burst控制
Google Guava中的RateLimiter,實際上就實現了Token Bucket的演算法。Google搜尋看到有些開源專案的issues,要把自己寫的Limiter換成了它。
它支援兩種獲取permits介面,一種是如果拿不到立刻返回false,一種會阻塞等待一段時間看能不能拿到。
Leacky Bucket演算法預設一開始水桶是空的,可以立即就接收最多burst的請求,而Token Bucket就要設定初始Token的數量。
RateLimiter有兩個子類,一個是WarmingUp,一個是Bursty。
- WarmingUp,burst = warmUp時間/固定token新增間隔,初始token數量 = burst,有演算法保證系統總是相對平滑。
- Bursty, burst = rate或另外的引數設定,初始token數量 = 0 ,當系統冷了一段時間,支援突發到burst。
Guava以micros為時間單位,計算token的變化。
參考文章
https://github.com/springside/springside4/wiki/Rate-Limiter
http://xiaobaoqiu.github.io/blog/2015/07/02/ratelimiter/