Guava RateLimiter的實(shí)現(xiàn)

限流

高并發(fā)系統(tǒng)有三大利器:緩存 带饱、限流 毡代、降級(jí)。
對(duì)于限流的實(shí)現(xiàn)勺疼,有多種算法:計(jì)數(shù)器教寂,漏桶法,令牌桶法执庐。
計(jì)數(shù)器法無(wú)法應(yīng)對(duì)極短時(shí)間內(nèi)的過(guò)量請(qǐng)求酪耕,而漏桶法無(wú)法處理短時(shí)間內(nèi)的突發(fā)請(qǐng)求,而令牌桶法能夠解決上述兩個(gè)問(wèn)題轨淌。所以迂烁,一般常用的是令牌桶法。
這里的限流與 Spring Cloud 的 Hystrix 的限流差異比較大递鹉,前者是“保護(hù)下游”盟步,后者是為了“保護(hù)自我”。并且躏结,RateLimiter 關(guān)心的其實(shí)是“流量整形”却盘,將不規(guī)整流量在一定速度內(nèi)規(guī)整。

Guava RateLimiter

Guava類庫(kù)中提供了令牌痛限流器的工具類RateLimiter媳拴,下面黄橘,我們具體看下Guava中令牌桶的具體實(shí)現(xiàn)。

RateLimiter的使用:

  1. 首先通過(guò)RateLimiter.create(1);創(chuàng)建一個(gè)限流器禀挫,參數(shù)代表每秒生成的令牌數(shù)
  2. 通過(guò)limiter.acquire(i);來(lái)以阻塞的方式獲取令牌旬陡,
    也可以通過(guò)tryAcquire(int permits, long timeout, TimeUnit unit)來(lái)設(shè)置等待超時(shí)時(shí)間的方式獲取令牌,如果超timeout為0语婴,則代表非阻塞描孟,獲取不到立即返回驶睦。

RateLimiter的實(shí)現(xiàn)

如何持續(xù)產(chǎn)生令牌?
接近現(xiàn)實(shí)生活的想法是匿醒,由一個(gè)單獨(dú)的線程定時(shí)向桶中放入token(其實(shí)就是對(duì)一個(gè)計(jì)數(shù)進(jìn)行增加)场航,但這樣做會(huì)無(wú)謂的浪費(fèi)處理器資源。
另一種解法則是延遲計(jì)算廉羔,它是在嘗試獲取令牌時(shí)溉痢,根據(jù)上次產(chǎn)生空閑令牌的時(shí)間點(diǎn)和令牌產(chǎn)生的速率來(lái)計(jì)算等待時(shí)間以及下次產(chǎn)生新的空閑令牌的時(shí)間點(diǎn)。
具體的代碼如下憋他,主要邏輯在reserveNextTicket中:

 public void acquire(int permits) {
    checkPermits(permits);
    long microsToWait;
    synchronized (mutex) {
        microsToWait = reserveNextTicket(permits, readSafeMicros());
    }
    ticker.sleepMicrosUninterruptibly(microsToWait);
  }
  
    /**
     * Reserves next ticket and returns the wait time that the caller must wait             for.
     */
    private long reserveNextTicket(double requiredPermits, long nowMicros) {
        resync(nowMicros);
        long microsToNextFreeTicket = nextFreeTicketMicros - nowMicros;
        double storedPermitsToSpend = Math.min(requiredPermits,                                     this.storedPermits);
        double freshPermits = requiredPermits - storedPermitsToSpend;

        long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend)
    + (long) (freshPermits * stableIntervalMicros);

        this.nextFreeTicketMicros = nextFreeTicketMicros + waitMicros;
        this.storedPermits -= storedPermitsToSpend;
        return microsToNextFreeTicket;
  }

具體的講孩饼,每次aquire都會(huì)調(diào)用resync計(jì)算桶中的令牌數(shù)竹挡,每次aquire后都會(huì)計(jì)算下一個(gè)可用的token的產(chǎn)生時(shí)刻nextFreeTicketMicros,aquire時(shí)揪罕,會(huì)將nextFreeTicketMicros減去當(dāng)前時(shí)刻,得到的就是等待時(shí)間好啰,同時(shí)會(huì)更新存儲(chǔ)的token數(shù)目轩娶,以及nextFreeTicketMicros。

如上框往,是獲取令牌的主要邏輯。

兩種RateLimiter

Guava中的RateLimiter有兩種實(shí)現(xiàn):

  • WarmingUp(令牌生成速度緩慢提升到穩(wěn)定值)
  • Bursty(令牌生成速度恒定)

當(dāng)服務(wù)一段時(shí)間沒(méi)有被使用時(shí)搅窿,RateLimiter會(huì)積累一定數(shù)目的令牌,從服務(wù)的角度來(lái)看男应,這時(shí)有兩種情況:
(1)服務(wù)有大量的空閑資源,可供調(diào)用者使用娱仔;—— BurstyRateLimiter
(2)由于長(zhǎng)時(shí)間沒(méi)有使用沐飘,緩存等功能失效,啟動(dòng)時(shí)需要預(yù)熱操作耐朴;—— WarmingUpRateLimiter

預(yù)熱版本W(wǎng)armingUpRateLimiter的特別之處在于
(1)桶中令牌數(shù)目的算法
(2)下次新的可用令牌產(chǎn)生的時(shí)間的算法:
如下圖


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盹憎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子影晓,更是在濱河造成了極大的恐慌,老刑警劉巖挂签,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異饵婆,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)草穆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)搓译,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人诗祸,你說(shuō)我怎么就攤上這事≈甭” “怎么了怀樟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)械荷。 經(jīng)常有香客問(wèn)我虑灰,道長(zhǎng),這世上最難降的妖魔是什么穆咐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮崖叫,結(jié)果婚禮上拍柒,老公的妹妹穿的比我還像新娘心傀。我一直安慰自己拆讯,他們只是感情好养叛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布疆液。 她就那樣靜靜地躺著,像睡著了一般潘飘。 火紅的嫁衣襯著肌膚如雪掉缺。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天眶明,我揣著相機(jī)與錄音,去河邊找鬼丑瞧。 笑死蜀肘,一個(gè)胖子當(dāng)著我的面吹牛绊汹,可吹牛的內(nèi)容都是我干的扮宠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼获雕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼收捣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起坏晦,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤昆婿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后仓蛆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體挎春,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豆拨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年能庆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弥搞。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡渠旁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顾腊,到底是詐尸還是另有隱情,我是刑警寧澤杂靶,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布吗垮,位于F島的核電站,受9級(jí)特大地震影響抱既,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜防泵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一捷泞、第九天 我趴在偏房一處隱蔽的房頂上張望足删。 院中可真熱鬧锁右,春花似錦、人聲如沸咏瑟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)余寥。三九已至悯森,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓢姻,已是汗流浹背音诈。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留改艇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓摔桦,卻偏偏與公主長(zhǎng)得像承疲,于是被迫代替她去往敵國(guó)和親邻耕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子燕鸽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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