1. 程式人生 > >喬木人 的 技術專欄

喬木人 的 技術專欄


原理介紹

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/