基于RateLimiter的服務(wù)接口限流實例

前景回顧:
《基于計數(shù)器的服務(wù)接口限流實例》

一、RateLimit中acquire的使用

在前面這篇文章中阶祭,我們使用了計數(shù)器來做服務(wù)接口的限流绎签,它最大的問題在于岛蚤,無法將請求均勻地分攤到單位時間內(nèi)的每個時間段上。行業(yè)術(shù)語就是無法平滑地分攤請求到涂。

本文的主角Guava中的RateLimiter就可以很好地平滑地分攤請求脊框。關(guān)于RateLimiter所涉及的漏桶及令牌桶算法原理,本文不再贅述践啄,可以參考文末的參考文章浇雹。

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>

RateLimiter的使用非常簡單,如下是最基本的使用實例:

@Slf4j
@RestController
public class UserMailRest {
    /**
     * 每秒投入2個令牌
     * */
    private RateLimiter rateLimiter = RateLimiter.create(2);

    @GetMapping("/getUserMail")
    public String getUserMail(){
        rateLimiter.acquire();
        log.info("請求得到了服務(wù)屿讽!");
        return "OK";
    }
}

如上代碼的作用就是規(guī)定每秒產(chǎn)生2個令牌昭灵,控制一秒內(nèi)最多只能有2個請求得到服務(wù)。按照RateLimiter的設(shè)計原則伐谈,這兩個令牌的投放時間間隔為1/2=0.5秒烂完,如此,能達到每隔0.5秒接受一個請求對其服務(wù)的目的衩婚。

我們使用Jmeter作為測試工具窜护,設(shè)置10個用戶線程,在一秒內(nèi)各自發(fā)起一次請求非春。

得到的結(jié)果如下:

2019-12-23 21:32:44.714  : 請求得到了服務(wù)柱徙!
2019-12-23 21:32:44.809  : 請求得到了服務(wù)!
2019-12-23 21:32:44.910  : 請求得到了服務(wù)奇昙!
2019-12-23 21:32:45.217  : 請求得到了服務(wù)护侮!
2019-12-23 21:32:45.714  : 請求得到了服務(wù)!
2019-12-23 21:32:46.264  : 請求得到了服務(wù)储耐!
2019-12-23 21:32:46.714  : 請求得到了服務(wù)羊初!
2019-12-23 21:32:47.214  : 請求得到了服務(wù)!
2019-12-23 21:32:47.714  : 請求得到了服務(wù)!
2019-12-23 21:32:48.214  : 請求得到了服務(wù)长赞!

現(xiàn)在模擬下這10個請求發(fā)起后晦攒,服務(wù)端都發(fā)生了什么:

  • 40秒,服務(wù)器啟動得哆,此時沒有請求到來脯颜,服務(wù)器中積累了2個令牌;
  • 40秒~44秒贩据,此時還是沒有請求到來栋操,服務(wù)器每秒都會產(chǎn)生2個令牌,但是因為前面存儲的令牌沒有被消費饱亮,而當前最多只能存放2個令牌矾芙,所以在此期間產(chǎn)生的令牌全部被放棄;
  • 44秒714的時候近上,第一個請求到來剔宪,此時服務(wù)器已經(jīng)存放了兩個歷史令牌,所以請求不用等待戈锻,直接獲取令牌得到服務(wù)歼跟;
  • 44秒809,第二個請求到來格遭,同樣立馬得到服務(wù)哈街;
  • 44秒910,第三個請求獲取了44秒下半秒本來就應該產(chǎn)生的一個令牌拒迅,因此也能立馬得到服務(wù)骚秦;
  • 45秒217,第四個請求獲取了45秒上半秒本來就應該產(chǎn)生的一個令牌...

以此類推璧微,可以看到作箍,我們原本在1秒內(nèi)發(fā)起的10個請求,在5秒內(nèi)前硫,差不多每隔0.5秒被服務(wù)接受胞得。從而使得請求的時間分布變得平滑,不會在某一個毫秒內(nèi)集中被服務(wù)屹电。

只不過需要注意的是阶剑,RateLimiter會存儲空閑的令牌,但是最多只能存儲一個時間單位的令牌數(shù)目危号,從而會使得空閑后突然激增的請求也能得到服務(wù)牧愁。

二、RateLimiter中tryAcquire的使用

acquire的使用是為了將所有的請求平滑地分布到后續(xù)的時間段內(nèi)外莲,但有的時候猪半,請求實在太多了,我們需要對調(diào)用過于頻繁的請求給予拒絕服務(wù)的響應,此時就需要用到tryAcquire了磨确。

@Slf4j
@RestController
public class UserMailRest {
    /**
     * 每秒投入2個令牌
     * */
    private RateLimiter rateLimiter = RateLimiter.create(2);

    @GetMapping("/getUserMail")
    public String getUserMail(){
        if(!rateLimiter.tryAcquire()){
            log.warn("請求過于頻繁沽甥,拒絕服務(wù)!");
            return "請求過于頻繁俐填,拒絕服務(wù)安接!";
        }
        log.info("請求得到服務(wù)!");
        return "OK";
    }
}

如上只有在tryAcquire失敗的情況下英融,拒絕服務(wù),執(zhí)行結(jié)果如下:

2019-12-23 21:57:32.083  : 請求得到服務(wù)歇式!
2019-12-23 21:57:32.083  : 請求得到服務(wù)驶悟!
2019-12-23 21:57:32.126  : 請求得到服務(wù)!
2019-12-23 21:57:32.224  : 請求過于頻繁材失,拒絕服務(wù)痕鳍!
2019-12-23 21:57:32.324  : 請求過于頻繁,拒絕服務(wù)龙巨!
2019-12-23 21:57:32.426  : 請求過于頻繁笼呆,拒絕服務(wù)!
2019-12-23 21:57:32.526  : 請求過于頻繁旨别,拒絕服務(wù)诗赌!
2019-12-23 21:57:32.626  : 請求得到服務(wù)!
2019-12-23 21:57:32.726  : 請求過于頻繁秸弛,拒絕服務(wù)铭若!
2019-12-23 21:57:32.829  : 請求過于頻繁,拒絕服務(wù)递览!

同樣的叼屠,我們分析下服務(wù)端都發(fā)生了什么:

  • 30秒,服務(wù)器啟動绞铃,此時沒有請求到來镜雨,服務(wù)器中積累了2個令牌;
  • 30秒~32秒儿捧,此時還是沒有請求到來荚坞,服務(wù)器每秒都會產(chǎn)生2個令牌,但是因為前面存儲的令牌沒有被消費纯命,而當前最多只能存放2個令牌西剥,所以在此期間產(chǎn)生的令牌全部被放棄;
  • 32秒083的時候亿汞,第一個請求到來瞭空,此時服務(wù)器已經(jīng)存放了兩個歷史令牌,所以請求不用等待,直接獲取令牌得到服務(wù)咆畏;
  • 32秒083南捂,第二個請求到來,同樣立馬得到服務(wù)旧找;
  • 32秒126溺健,第三個請求獲取了32秒上半秒本來就應該產(chǎn)生的一個令牌,因此也能立馬得到服務(wù)钮蛛;
  • 32秒224~32秒526鞭缭,這些請求都沒有令牌可以獲取,因為此時魏颓,32秒下半秒的令牌還沒有被釋放岭辣,因此,全部都拒絕服務(wù)甸饱;
  • 32秒626沦童,第八個請求獲得了32秒下半秒本來就應該產(chǎn)生的令牌,因此得到服務(wù)叹话;
  • 剩下的兩個請求都是在32秒下半秒發(fā)生的偷遗,因此獲取不到令牌,因此拒絕服務(wù)驼壶;

三氏豌、總結(jié)

好了,關(guān)于RateLimiter的常見使用方法主要就是以上講解的acquire以及tryAcquire辅柴,通過實例后的分析我們大致也能了解其工作原理箩溃。

RateLimiter相較于計數(shù)器的限流方案來說,最大的特點就是限制請求在單位時間內(nèi)平滑地對服務(wù)器進行訪問碌嘀,從而不會發(fā)生涣旨,在一個毫秒內(nèi)爆發(fā)全部的請求,瞬間壓垮服務(wù)的情況股冗。

但是霹陡,和計數(shù)器一樣,存在一個很致命的問題止状。它們都只是限制單位時間內(nèi)請求的數(shù)量烹棉,但并不能限制服務(wù)器上并發(fā)的數(shù)量。比如怯疤,1秒內(nèi)允許200個訪問浆洗,但是這200個訪問是很耗時的LongCall,從而導致第n秒的時候集峦,服務(wù)器上可能就會有200*n個線程的并發(fā)伏社,最終超過系統(tǒng)能承載的最大并發(fā)數(shù)抠刺,壓垮系統(tǒng)。

四摘昌、參考文獻:

RateLimiter解析(一) ——設(shè)計哲學與快速使用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末速妖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子聪黎,更是在濱河造成了極大的恐慌罕容,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稿饰,死亡現(xiàn)場離奇詭異锦秒,居然都是意外死亡,警方通過查閱死者的電腦和手機湘纵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門脂崔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人梧喷,你說我怎么就攤上這事〔备溃” “怎么了铺敌?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵,是天一觀的道長屁擅。 經(jīng)常有香客問我偿凭,道長,這世上最難降的妖魔是什么派歌? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任弯囊,我火速辦了婚禮,結(jié)果婚禮上胶果,老公的妹妹穿的比我還像新娘匾嘱。我一直安慰自己,他們只是感情好早抠,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布霎烙。 她就那樣靜靜地躺著,像睡著了一般蕊连。 火紅的嫁衣襯著肌膚如雪悬垃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天甘苍,我揣著相機與錄音尝蠕,去河邊找鬼。 笑死载庭,一個胖子當著我的面吹牛看彼,可吹牛的內(nèi)容都是我干的廊佩。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼闲昭,長吁一口氣:“原來是場噩夢啊……” “哼罐寨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起序矩,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤鸯绿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后簸淀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓶蝴,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年租幕,在試婚紗的時候發(fā)現(xiàn)自己被綠了舷手。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡劲绪,死狀恐怖男窟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情贾富,我是刑警寧澤歉眷,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站颤枪,受9級特大地震影響汗捡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜畏纲,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一扇住、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盗胀,春花似錦艘蹋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至米间,卻和暖如春强品,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屈糊。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工的榛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人逻锐。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓夫晌,卻偏偏與公主長得像雕薪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子晓淀,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

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

  • 緩存 緩存比較好理解窃蹋,在大型高并發(fā)系統(tǒng)中坚芜,如果沒有緩存數(shù)據(jù)庫將分分鐘被爆窃判,系統(tǒng)也會瞬間癱瘓寄摆。使用緩存不單單能夠提升...
    阿斯蒂芬2閱讀 12,163評論 1 28
  • 聊聊高并發(fā)系統(tǒng)限流特技-1來自開濤的博客 在開發(fā)高并發(fā)系統(tǒng)時有三把利器用來保護系統(tǒng):緩存、降級和限流懦窘。緩存的目的是...
    meng_philip123閱讀 6,647評論 1 20
  • 前言 最近需要在網(wǎng)關(guān)層做一個限流的需求前翎,由于需要對一個機房內(nèi)的集群做統(tǒng)一的限流管理,所以可能需要用到redis畅涂,而...
    ro9er閱讀 2,692評論 1 12
  • Vi有三種基本工作模式: 命令模式 文本輸入模式 末行模式港华。 命令行模式 任何時候,不管用戶處于何種模式午衰,只要按一...
    子丿龍閱讀 285評論 0 1
  • 你們在面對客戶的時候立宜,是否經(jīng)常有這種感覺,客戶真的實在是太挑剔了臊岸,總是抱怨很多問題赘理,但是有沒有想過其實客戶的抱怨就...
    我是彩虹小姐閱讀 326評論 0 3