【Guava】RateLimiter類

Guava官方文檔-RateLimiter類

原文連接 做者:Dimitris Andreou  譯者:魏嘉鵬 校對:方騰飛token_buckethtml

RateLimiter 從概念上來說,速率限制器會在可配置的速率下分配許可證。若是必要的話,每一個acquire() 會阻塞當前線程直到許可證可用後獲取該許可證。一旦獲取到許可證,不須要再釋放許可證。java

校對注:RateLimiter使用的是一種叫令牌桶的流控算法,RateLimiter會按照必定的頻率往桶裏扔令牌,線程拿到令牌才能執行,好比你但願本身的應用程序QPS不要超過1000,那麼RateLimiter設置1000的速率後,就會每秒往桶裏扔1000個令牌。git

1    com.google.common.util.concurrent.RateLimiter
2     
3    @ThreadSafe
4    @Betapublic
5    abstract class RateLimiter extends Object

 


RateLimiter常常用於限制對一些物理資源或者邏輯資源的訪問速率。與Semaphore 相比,Semaphore 限制了併發訪問的數量而不是使用速率。(注意儘管併發性和速率是緊密相關的,好比參考Little定律
算法

經過設置許可證的速率來定義RateLimiter。在默認配置下,許可證會在固定的速率下被分配,速率單位是每秒多少個許可證。爲了確保維護配置的速率,許可會被平穩地分配,許可之間的延遲會作調整。
可能存在配置一個擁有預熱期的RateLimiter 的狀況,在這段時間內,每秒分配的許可數會穩定地增加直到達到穩定的速率。編程

舉例來講明如何使用RateLimiter,想象下咱們須要處理一個任務列表,但咱們不但願每秒的任務提交超過兩個:併發

1    //速率是每秒兩個許可
2    final RateLimiter rateLimiter = RateLimiter.create(2.0);
3     
4    void submitTasks(List tasks, Executor executor) {
5        for (Runnable task : tasks) {
6            rateLimiter.acquire(); // 也許須要等待
7            executor.execute(task);
8        }
9    }

 

再舉另一個例子,想象下咱們製造了一個數據流,並但願以每秒5kb的速率處理它。能夠經過要求每一個字節表明一個許可,而後指定每秒5000個許可來完成:post

1    // 每秒5000個許可
2    final RateLimiter rateLimiter = RateLimiter.create(5000.0);
3     
4    void submitPacket(byte[] packet) {
5        rateLimiter.acquire(packet.length);
6        networkService.send(packet);
7    }

 

有一點很重要,那就是請求的許可數歷來不會影響到請求自己的限制(調用acquire(1) 和調用acquire(1000) 將獲得相同的限制效果,若是存在這樣的調用的話),但會影響下一次請求的限制,也就是說,若是一個高開銷的任務抵達一個空閒的RateLimiter,它會被立刻許可,可是下一個請求會經歷額外的限制,從而來償付高開銷任務。注意:RateLimiter 並不提供公平性的保證。ui

Since:13.0  做者:   Dimitris Andreougoogle

方法摘要

修飾符和類型 方法和描述
double acquire()
從RateLimiter獲取一個許可,該方法會被阻塞直到獲取到請求
double acquire(int permits)
從RateLimiter獲取指定許可數,該方法會被阻塞直到獲取到請求
static RateLimiter create(double permitsPerSecond)
根據指定的穩定吞吐率建立RateLimiter,這裏的吞吐率是指每秒多少量可數(一般是指QPS,每秒多少查詢)
static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit)
根據指定的穩定吞吐率和預熱期來建立RateLimiter,這裏的吞吐率是指每秒多少量可數(一般是指QPS,每秒多少個請求量),在這段預熱時間內,RateLimiter每秒分配的許可數會平穩地增加直到預熱期結束時達到其最大速率。(只要存在足夠請求數來使其飽和)
double getRate()
返回RateLimiter 配置中的穩定速率,該速率單位是每秒多少量可數
void setRate(double permitsPerSecond)
更新RateLimite的穩定速率,參數permitsPerSecond 由構造RateLimiter的工廠方法提供。
String toString()
返回對象的字符表現形式
boolean tryAcquire()
從RateLimiter 獲取許可,若是該許可能夠在無延遲下的狀況下當即獲取獲得的話
boolean tryAcquire(int permits)
從RateLimiter 獲取許可數,若是該許可數能夠在無延遲下的狀況下當即獲取獲得的話
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
從RateLimiter 獲取指定許可數若是該許可數能夠在不超過timeout的時間內獲取獲得的話,或者若是沒法在timeout 過時以前獲取獲得許可數的話,那麼當即返回false (無需等待)
boolean tryAcquire(long timeout, TimeUnit unit)
從RateLimiter 獲取許可若是該許可能夠在不超過timeout的時間內獲取獲得的話,或者若是沒法在timeout 過時以前獲取獲得許可的話,那麼當即返回false(無需等待)
從java.lang.Object 類繼承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

方法細節

create
public static RateLimiter create(double permitsPerSecond)
根據指定的穩定吞吐率建立RateLimiter,這裏的吞吐率是指每秒多少量可數(一般是指QPS,每秒多少查詢)。
The returned RateLimiter ensures that on average no more than permitsPerSecond are issued during any given second, with sustained requests being smoothly spread over each second. When the incoming request rate exceeds permitsPerSecond the rate limiter will release one permit every (1.0 / permitsPerSecond) seconds. When the rate limiter is unused, bursts of up to permitsPerSecond permits will be allowed, with subsequent requests being smoothly limited at the stable rate of permitsPerSecond.
返回的RateLimiter 確保了在平均狀況下,每秒發佈的許可數不會超過permitsPerSecond,每秒鐘會持續發送請求。當傳入請求速率超過permitsPerSecond,速率限制器會每秒釋放一個許可(1.0 / permitsPerSecond 這裏是指設定了permitsPerSecond爲1.0) 。當速率限制器閒置時,容許許可數暴增到permitsPerSecond,隨後的請求會被平滑地限制在穩定速率permitsPerSecond中。
參數:
permitsPerSecond – 返回的RateLimiter的速率,意味着每秒有多少個許可變成有效。
拋出:
IllegalArgumentException – 若是permitsPerSecond爲負數或者爲0
create
public static RateLimiter create(double permitsPerSecond,long warmupPeriod,TimeUnit unit)
根據指定的穩定吞吐率和預熱期來建立RateLimiter,這裏的吞吐率是指每秒多少量可數(一般是指QPS,每秒多少查詢),在這段預熱時間內,RateLimiter每秒分配的許可數會平穩地增加直到預熱期結束時達到其最大速率(只要存在足夠請求數來使其飽和)。一樣地,若是RateLimiter 在warmupPeriod時間內閒置不用,它將會逐步地返回冷卻狀態。也就是說,它會像它第一次被建立般經歷一樣的預熱期。返回的RateLimiter 主要用於那些須要預熱期的資源,這些資源實際上知足了請求(好比一個遠程服務),而不是在穩定(最大)的速率下能夠當即被訪問的資源。返回的RateLimiter 在冷卻狀態下啓動(即預熱期將會緊跟着發生),而且若是被長期閒置不用,它將回到冷卻狀態。
參數:

 

  • permitsPerSecond – 返回的RateLimiter的速率,意味着每秒有多少個許可變成有效。
  • warmupPeriod – 在這段時間內RateLimiter會增長它的速率,在抵達它的穩定速率或者最大速率以前
  • unit – 參數warmupPeriod 的時間單位

拋出:spa

  • IllegalArgumentException – 若是permitsPerSecond爲負數或者爲0
setRate
public final void setRate(double permitsPerSecond)
更新RateLimite的穩定速率,參數permitsPerSecond 由構造RateLimiter的工廠方法提供。調用該方法後,當前限制線程不會被喚醒,所以他們不會注意到最新的速率;只有接下來的請求才會。須要注意的是,因爲每次請求償還了(經過等待,若是須要的話)上一次請求的開銷,這意味着牢牢跟着的下一個請求不會被最新的速率影響到,在調用了setRate 以後;它會償還上一次請求的開銷,這個開銷依賴於以前的速率。RateLimiter的行爲在任何方式下都不會被改變,好比若是 RateLimiter 有20秒的預熱期配置,在此方法被調用後它仍是會進行20秒的預熱。
參數:
permitsPerSecond – RateLimiter的新的穩定速率
拋出:
IllegalArgumentException – 若是permitsPerSecond爲負數或者爲0
getRate
public final double getRate()
返回RateLimiter 配置中的穩定速率,該速率單位是每秒多少量可數。它的初始值至關於構造這個RateLimiter的工廠方法中的參數permitsPerSecond ,而且只有在調用setRate(double)後纔會被更新。
acquire
public double acquire()
從RateLimiter獲取一個許可,該方法會被阻塞直到獲取到請求。若是存在等待的狀況的話,告訴調用者獲取到該請求所須要的睡眠時間。該方法等同於acquire(1)。
返回:
time spent sleeping to enforce rate, in seconds; 0.0 if not rate-limited
執行速率的所須要的睡眠時間,單位爲妙;若是沒有則返回0
Since:
16.0 (版本13.0沒有返回值)
acquire
public double acquire(int permits)
從RateLimiter獲取指定許可數,該方法會被阻塞直到獲取到請求數。若是存在等待的狀況的話,告訴調用者獲取到這些請求數所須要的睡眠時間。
參數:
permits – 須要獲取的許可數
返回:
執行速率的所須要的睡眠時間,單位爲妙;若是沒有則返回0
拋出:
IllegalArgumentException – 若是請求的許可數爲負數或者爲0
Since:
16.0 (版本13.0沒有返回值)
tryAcquire
public boolean tryAcquire(long timeout,TimeUnit unit)
從RateLimiter獲取許可若是該許可能夠在不超過timeout的時間內獲取獲得的話,或者若是沒法在timeout 過時以前獲取獲得許可的話,那麼當即返回false(無需等待)。該方法等同於tryAcquire(1, timeout, unit)。
參數:

 

  • timeout – 等待許可的最大時間,負數以0處理
  • unit – 參數timeout 的時間單位

返回:
true表示獲取到許可,反之則是false
拋出:
IllegalArgumentException – 若是請求的許可數爲負數或者爲0

tryAcquire
public boolean tryAcquire(int permits)
從RateLimiter 獲取許可數,若是該許可數能夠在無延遲下的狀況下當即獲取獲得的話。該方法等同於tryAcquire(permits, 0, anyUnit)。
參數:
permits – 須要獲取的許可數
返回:
true表示獲取到許可,反之則是false
拋出:
IllegalArgumentException – 若是請求的許可數爲負數或者爲0
Since:
14.0
tryAcquire
public boolean tryAcquire()
從RateLimiter 獲取許可,若是該許可能夠在無延遲下的狀況下當即獲取獲得的話。
該方法等同於tryAcquire(1)。
返回:
true表示獲取到許可,反之則是false
Since:
14.0
tryAcquire
public boolean tryAcquire(int permits,long timeout,TimeUnit unit)
從RateLimiter 獲取指定許可數若是該許可數能夠在不超過timeout的時間內獲取獲得的話,或者若是沒法在timeout 過時以前獲取獲得許可數的話,那麼當即返回false (無需等待)。
參數:
permits – 須要獲取的許可數
timeout – 等待許可數的最大時間,負數以0處理
unit – 參數timeout 的時間單位
返回:
true表示獲取到許可,反之則是false
拋出:
IllegalArgumentException -若是請求的許可數爲負數或者爲0
toString
public String toString()
如下描述複製於java.lang.Object類。
返回對象的字符表現形式。一般來說,toString 方法返回一個「文本化呈現」對象的字符串。
結果應該是一個簡明但易於讀懂的信息表達式。建議全部子類都重寫該方法。
toString 方法返回一個由實例的類名,字符’@’和以無符號十六進制表示的對象的哈希值組成的字符串。換句話說,該方法返回的字符串等同於:
getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
重載:
Object類的toString方法
返回:
對象的字符表現形式

原創文章,轉載請註明: 轉載自併發編程網 – ifeve.com本文連接地址: Guava官方文檔-RateLimiter類

相關文章
相關標籤/搜索