Guava RateLimiter 學(xué)習(xí)

Google開(kāi)源工具包Guava提供了限流工具類RateLimiter,該類基于令牌桶算法(Token Bucket)來(lái)完成限流

RateLimiter 從概念上來(lái)講,速率限制器會(huì)在可配置的速率下分配許可證胯杭。如果必要的話髓霞,每個(gè)acquire() 會(huì)阻塞當(dāng)前線程直到許可證可用后獲取該許可證兰伤。一旦獲取到許可證端仰,不需要再釋放許可證泳猬。

注:RateLimiter使用的是一種叫令牌桶的流控算法,RateLimiter會(huì)按照一定的頻率往桶里扔令牌盗冷,線程拿到令牌才能執(zhí)行怠苔,比如你希望自己的應(yīng)用程序QPS不要超過(guò)1000,那么RateLimiter設(shè)置1000的速率后仪糖,就會(huì)每秒往桶里扔1000個(gè)令牌柑司。

RateLimiter是一個(gè)abstract類,但它提供了幾個(gè)static方法用于創(chuàng)建RateLimiter:

通過(guò)設(shè)置許可證的速率permitsPerSecond來(lái)定義RateLimiter。在默認(rèn)配置下乓诽,許可證會(huì)在固定的速率下被分配帜羊。為了確保維護(hù)配置的速率

可能存在需要使用一個(gè)擁有預(yù)熱期的RateLimiter 的情況,通過(guò)設(shè)置熱身期(warmup period)參數(shù)鸠天。在這段時(shí)間內(nèi),每秒分配的許可數(shù)會(huì)穩(wěn)定地增長(zhǎng)直到達(dá)到穩(wěn)定的速率帐姻,如果RateLimiter在熱身期沒(méi)有足夠的請(qǐng)求(unused),則起速率會(huì)逐漸降低到冷卻狀態(tài)稠集。

/**
* 創(chuàng)建一個(gè)穩(wěn)定輸出令牌的RateLimiter奶段,保證了平均每秒不超過(guò)permitsPerSecond個(gè)請(qǐng)求
* 當(dāng)請(qǐng)求到來(lái)的速度超過(guò)了permitsPerSecond,保證每秒只處理permitsPerSecond個(gè)請(qǐng)求
*/
public static RateLimiter create(double permitsPerSecond);

/**
* 創(chuàng)建一個(gè)穩(wěn)定輸出令牌的RateLimiter剥纷,保證了平均每秒不超過(guò)permitsPerSecond個(gè)請(qǐng)求
* 還包含一個(gè)熱身期(warmup period),熱身期內(nèi)痹籍,RateLimiter會(huì)平滑的將其釋放令牌的速率加大,直到起達(dá)到最大速率
* 同樣晦鞋,如果RateLimiter在熱身期沒(méi)有足夠的請(qǐng)求(unused),則起速率會(huì)逐漸降低到冷卻狀態(tài)
* 
* 設(shè)計(jì)這個(gè)的意圖是為了滿足那種資源提供方需要熱身時(shí)間蹲缠,而不是每次訪問(wèn)都能提供穩(wěn)定速率的服務(wù)的情況(比如帶緩存服務(wù),需要定期刷新緩存的)
* 參數(shù)warmupPeriod和unit決定了其從冷卻狀態(tài)到達(dá)最大速率的時(shí)間
*/
public static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit);

提供了兩個(gè)獲取令牌的方法,不帶參數(shù)表示獲取一個(gè)令牌.如果沒(méi)有令牌則一直等待,返回等待的時(shí)間(單位為秒),沒(méi)有被限流則直接返回0.0:

public double acquire();

public double acquire(int permits);

嘗試獲取令牌,分為待超時(shí)時(shí)間和不帶超時(shí)時(shí)間兩種:

public boolean tryAcquire();
//嘗試獲取一個(gè)令牌,立即返回
public boolean tryAcquire(int permits);
public boolean tryAcquire(long timeout, TimeUnit unit);
//嘗試獲取permits個(gè)令牌,帶超時(shí)時(shí)間
public boolean tryAcquire(int permits, long timeout, TimeUnit unit);
RateLimiter方法摘要
修飾符和類型 方法和描述
double acquire() 從RateLimiter獲取一個(gè)許可悠垛,該方法會(huì)被阻塞直到獲取到請(qǐng)求
double acquire(int permits) 從RateLimiter獲取指定許可數(shù)线定,該方法會(huì)被阻塞直到獲取到請(qǐng)求
static RateLimiter create(double permitsPerSecond) 根據(jù)指定的穩(wěn)定吞吐率創(chuàng)建RateLimiter,這里的吞吐率是指每秒多少許可數(shù)(通常是指QPS确买,每秒多少查詢)
static RateLimiter create(double permitsPerSecond, long warmupPeriod, TimeUnit unit) 根據(jù)指定的穩(wěn)定吞吐率和預(yù)熱期來(lái)創(chuàng)建RateLimiter斤讥,這里的吞吐率是指每秒多少許可數(shù)(通常是指QPS,每秒多少個(gè)請(qǐng)求量)湾趾,在這段預(yù)熱時(shí)間內(nèi)芭商,RateLimiter每秒分配的許可數(shù)會(huì)平穩(wěn)地增長(zhǎng)直到預(yù)熱期結(jié)束時(shí)達(dá)到其最大速率。(只要存在足夠請(qǐng)求數(shù)來(lái)使其飽和)
double getRate() 返回RateLimiter 配置中的穩(wěn)定速率搀缠,該速率單位是每秒多少許可數(shù)
void setRate(double permitsPerSecond) 更新RateLimite的穩(wěn)定速率铛楣,參數(shù)permitsPerSecond 由構(gòu)造RateLimiter的工廠方法提供。
String toString() 返回對(duì)象的字符表現(xiàn)形式
boolean tryAcquire() 從RateLimiter 獲取許可艺普,如果該許可可以在無(wú)延遲下的情況下立即獲取得到的話
boolean tryAcquire(int permits) 從RateLimiter 獲取許可數(shù)簸州,如果該許可數(shù)可以在無(wú)延遲下的情況下立即獲取得到的話
boolean tryAcquire(int permits, long timeout, TimeUnit unit) 從RateLimiter 獲取指定許可數(shù)如果該許可數(shù)可以在不超過(guò)timeout的時(shí)間內(nèi)獲取得到的話,或者如果無(wú)法在timeout 過(guò)期之前獲取得到許可數(shù)的話衷敌,那么立即返回false (無(wú)需等待)
boolean tryAcquire(long timeout, TimeUnit unit) 從RateLimiter 獲取許可如果該許可可以在不超過(guò)timeout的時(shí)間內(nèi)獲取得到的話勿侯,或者如果無(wú)法在timeout 過(guò)期之前獲取得到許可的話,那么立即返回false(無(wú)需等待)
方法細(xì)節(jié)
create

public static RateLimiter create(double permitsPerSecond)

根據(jù)指定的穩(wěn)定吞吐率創(chuàng)建RateLimiter缴罗,這里的吞吐率是指每秒多少許可數(shù)(通常是指QPS助琐,每秒多少查詢)。

返回的RateLimiter 確保了在平均情況下面氓,每秒發(fā)布的許可數(shù)不會(huì)超過(guò)permitsPerSecond兵钮,每秒鐘會(huì)持續(xù)發(fā)送請(qǐng)求。當(dāng)傳入請(qǐng)求速率超過(guò)permitsPerSecond舌界,速率限制器會(huì)每秒釋放一個(gè)許可(1.0 / permitsPerSecond 這里是指設(shè)定了permitsPerSecond為1.0) 掘譬。當(dāng)速率限制器閑置時(shí),允許許可數(shù)暴增到permitsPerSecond呻拌,隨后的請(qǐng)求會(huì)被平滑地限制在穩(wěn)定速率permitsPerSecond中葱轩。

參數(shù):

permitsPerSecond – 返回的RateLimiter的速率,意味著每秒有多少個(gè)許可變成有效。

拋出:

IllegalArgumentException – 如果permitsPerSecond為負(fù)數(shù)或者為0

create

public static RateLimiter create(double permitsPerSecond,long warmupPeriod,TimeUnit unit)

根據(jù)指定的穩(wěn)定吞吐率和預(yù)熱期來(lái)創(chuàng)建RateLimiter靴拱,這里的吞吐率是指每秒多少許可數(shù)(通常是指QPS垃喊,每秒多少查詢),在這段預(yù)熱時(shí)間內(nèi)袜炕,RateLimiter每秒分配的許可數(shù)會(huì)平穩(wěn)地增長(zhǎng)直到預(yù)熱期結(jié)束時(shí)達(dá)到其最大速率(只要存在足夠請(qǐng)求數(shù)來(lái)使其飽和)本谜。同樣地,如果RateLimiter 在warmupPeriod時(shí)間內(nèi)閑置不用偎窘,它將會(huì)逐步地返回冷卻狀態(tài)乌助。也就是說(shuō),它會(huì)像它第一次被創(chuàng)建般經(jīng)歷同樣的預(yù)熱期陌知。返回的RateLimiter 主要用于那些需要預(yù)熱期的資源他托,這些資源實(shí)際上滿足了請(qǐng)求(比如一個(gè)遠(yuǎn)程服務(wù)),而不是在穩(wěn)定(最大)的速率下可以立即被訪問(wèn)的資源纵诞。返回的RateLimiter 在冷卻狀態(tài)下啟動(dòng)(即預(yù)熱期將會(huì)緊跟著發(fā)生)上祈,并且如果被長(zhǎng)期閑置不用,它將回到冷卻狀態(tài)浙芙。

參數(shù):

permitsPerSecond – 返回的RateLimiter的速率登刺,意味著每秒有多少個(gè)許可變成有效。
warmupPeriod – 在這段時(shí)間內(nèi)RateLimiter會(huì)增加它的速率嗡呼,在抵達(dá)它的穩(wěn)定速率或者最大速率之前
unit – 參數(shù)warmupPeriod 的時(shí)間單位

拋出:

IllegalArgumentException – 如果permitsPerSecond為負(fù)數(shù)或者為0

setRate

public final void setRate(double permitsPerSecond)

更新RateLimite的穩(wěn)定速率纸俭,參數(shù)permitsPerSecond 由構(gòu)造RateLimiter的工廠方法提供。調(diào)用該方法后南窗,當(dāng)前限制線程不會(huì)被喚醒揍很,因此他們不會(huì)注意到最新的速率;只有接下來(lái)的請(qǐng)求才會(huì)万伤。需要注意的是窒悔,由于每次請(qǐng)求償還了(通過(guò)等待,如果需要的話)上一次請(qǐng)求的開(kāi)銷敌买,這意味著緊緊跟著的下一個(gè)請(qǐng)求不會(huì)被最新的速率影響到简珠,在調(diào)用了setRate 之后;它會(huì)償還上一次請(qǐng)求的開(kāi)銷虹钮,這個(gè)開(kāi)銷依賴于之前的速率聋庵。RateLimiter的行為在任何方式下都不會(huì)被改變,比如如果 RateLimiter 有20秒的預(yù)熱期配置芙粱,在此方法被調(diào)用后它還是會(huì)進(jìn)行20秒的預(yù)熱祭玉。

參數(shù):

permitsPerSecond – RateLimiter的新的穩(wěn)定速率

拋出:

IllegalArgumentException – 如果permitsPerSecond為負(fù)數(shù)或者為0

getRate

public final double getRate()

返回RateLimiter 配置中的穩(wěn)定速率,該速率單位是每秒多少許可數(shù)春畔。它的初始值相當(dāng)于構(gòu)造這個(gè)RateLimiter的工廠方法中的參數(shù)permitsPerSecond 脱货,并且只有在調(diào)用setRate(double)后才會(huì)被更新岛都。

acquire

public double acquire()

從RateLimiter獲取一個(gè)許可,該方法會(huì)被阻塞直到獲取到請(qǐng)求蹭劈。如果存在等待的情況的話疗绣,告訴調(diào)用者獲取到該請(qǐng)求所需要的睡眠時(shí)間线召。該方法等同于acquire(1)铺韧。

返回:

time spent sleeping to enforce rate, in seconds; 0.0 if not rate-limited
執(zhí)行速率的所需要的睡眠時(shí)間,單位為妙缓淹;如果沒(méi)有則返回0

acquire

public double acquire(int permits)

從RateLimiter獲取指定許可數(shù)哈打,該方法會(huì)被阻塞直到獲取到請(qǐng)求數(shù)。如果存在等待的情況的話讯壶,告訴調(diào)用者獲取到這些請(qǐng)求數(shù)所需要的睡眠時(shí)間料仗。

參數(shù):

permits – 需要獲取的許可數(shù)

返回:

執(zhí)行速率的所需要的睡眠時(shí)間,單位為妙伏蚊;如果沒(méi)有則返回0

拋出:

IllegalArgumentException – 如果請(qǐng)求的許可數(shù)為負(fù)數(shù)或者為0

tryAcquire

public boolean tryAcquire(long timeout,TimeUnit unit)

從RateLimiter獲取許可如果該許可可以在不超過(guò)timeout的時(shí)間內(nèi)獲取得到的話立轧,或者如果無(wú)法在timeout 過(guò)期之前獲取得到許可的話,那么立即返回false(無(wú)需等待)躏吊。該方法等同于tryAcquire(1, timeout, unit)氛改。

參數(shù):

timeout – 等待許可的最大時(shí)間,負(fù)數(shù)以0處理

unit – 參數(shù)timeout 的時(shí)間單位

返回:

true表示獲取到許可比伏,反之則是false

拋出:

IllegalArgumentException – 如果請(qǐng)求的許可數(shù)為負(fù)數(shù)或者為0

tryAcquire

public boolean tryAcquire(int permits)

從RateLimiter 獲取許可數(shù)胜卤,如果該許可數(shù)可以在無(wú)延遲下的情況下立即獲取得到的話。該方法等同于tryAcquire(permits, 0, anyUnit)赁项。

參數(shù):

permits – 需要獲取的許可數(shù)

返回:

true表示獲取到許可葛躏,反之則是false

拋出:

IllegalArgumentException – 如果請(qǐng)求的許可數(shù)為負(fù)數(shù)或者為0

tryAcquire

public boolean tryAcquire()

從RateLimiter 獲取許可,如果該許可可以在無(wú)延遲下的情況下立即獲取得到的話悠菜。

該方法等同于tryAcquire(1)舰攒。

返回:

true表示獲取到許可,反之則是false

tryAcquire

public boolean tryAcquire(int permits,long timeout,TimeUnit unit)

從RateLimiter 獲取指定許可數(shù)如果該許可數(shù)可以在不超過(guò)timeout的時(shí)間內(nèi)獲取得到的話悔醋,或者如果無(wú)法在timeout 過(guò)期之前獲取得到許可數(shù)的話摩窃,那么立即返回false (無(wú)需等待)。

參數(shù):

permits – 需要獲取的許可數(shù)
timeout – 等待許可數(shù)的最大時(shí)間篙顺,負(fù)數(shù)以0處理
unit – 參數(shù)timeout 的時(shí)間單位

返回:

true表示獲取到許可偶芍,反之則是false

拋出:

IllegalArgumentException -如果請(qǐng)求的許可數(shù)為負(fù)數(shù)或者為0

toString

public String toString()

以下描述復(fù)制于java.lang.Object類。

返回對(duì)象的字符表現(xiàn)形式德玫。通常來(lái)講匪蟀,toString 方法返回一個(gè)“文本化呈現(xiàn)”對(duì)象的字符串。

結(jié)果應(yīng)該是一個(gè)簡(jiǎn)明但易于讀懂的信息表達(dá)式宰僧。建議所有子類都重寫(xiě)該方法材彪。

toString 方法返回一個(gè)由實(shí)例的類名,字符’@’和以無(wú)符號(hào)十六進(jìn)制表示的對(duì)象的哈希值組成的字符串。換句話說(shuō)段化,該方法返回的字符串等同于:
getClass().getName() + ‘@’ + Integer.toHexString(hashCode())

重載:

Object類的toString方法

返回:

對(duì)象的字符表現(xiàn)形式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嘁捷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子显熏,更是在濱河造成了極大的恐慌雄嚣,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喘蟆,死亡現(xiàn)場(chǎng)離奇詭異缓升,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蕴轨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門港谊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人橙弱,你說(shuō)我怎么就攤上這事歧寺。” “怎么了棘脐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵斜筐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我荆残,道長(zhǎng)奴艾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任内斯,我火速辦了婚禮蕴潦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俘闯。我一直安慰自己潭苞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布真朗。 她就那樣靜靜地躺著此疹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遮婶。 梳的紋絲不亂的頭發(fā)上蝗碎,一...
    開(kāi)封第一講書(shū)人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音旗扑,去河邊找鬼蹦骑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛臀防,可吹牛的內(nèi)容都是我干的眠菇。 我是一名探鬼主播边败,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捎废!你這毒婦竟也來(lái)了笑窜?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤登疗,失蹤者是張志新(化名)和其女友劉穎排截,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體谜叹,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匾寝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荷腊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡急凰,死狀恐怖女仰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抡锈,我是刑警寧澤疾忍,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站床三,受9級(jí)特大地震影響一罩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撇簿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一聂渊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧四瘫,春花似錦汉嗽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)子姜。三九已至,卻和暖如春弓叛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诚纸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工撰筷, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咬清。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓闭专,卻偏偏與公主長(zhǎng)得像奴潘,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子影钉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 為何要做限制 系統(tǒng)使用下游資源時(shí)画髓,需要考慮下游資源所能提供資源能力。對(duì)于資源受限平委、處理能力不是很強(qiáng)的資源應(yīng)當(dāng)給予保...
    牛奶路閱讀 9,976評(píng)論 0 9
  • 緩存 緩存比較好理解奈虾,在大型高并發(fā)系統(tǒng)中,如果沒(méi)有緩存數(shù)據(jù)庫(kù)將分分鐘被爆廉赔,系統(tǒng)也會(huì)瞬間癱瘓肉微。使用緩存不單單能夠提升...
    阿斯蒂芬2閱讀 12,136評(píng)論 1 28
  • 前言 最近需要在網(wǎng)關(guān)層做一個(gè)限流的需求,由于需要對(duì)一個(gè)機(jī)房?jī)?nèi)的集群做統(tǒng)一的限流管理蜡塌,所以可能需要用到redis碉纳,而...
    ro9er閱讀 2,681評(píng)論 1 12
  • Guava源碼中很詳盡的解釋了RateLimiter的概念。 從概念上看馏艾,限流器以配置速率釋放允許的請(qǐng)求(perm...
    無(wú)名碼者閱讀 885評(píng)論 0 1
  • 去年放花千骨的那時(shí)候劳曹,我和爸爸合計(jì)給媽媽買了一臺(tái)電腦,買回來(lái)之后我很興奮的給媽媽下載各種軟件琅摩,整理電腦铁孵,然后在QQ...
    浜栲澶閱讀 164評(píng)論 0 0