一文帶你了解分布式神器-限流器
Guava RateLimiter
有沒有搞錯(cuò),別人都在提升系統(tǒng)的訪問(wèn)并發(fā)量,你卻在這搞限制?
我們都知道,服務(wù)器資源是有限的,當(dāng)把應(yīng)用部署在外網(wǎng)環(huán)境中,所有人都可以訪問(wèn)你的應(yīng)用,如果訪問(wèn)人數(shù)上去了,你的服務(wù)器是否能夠支持足夠量的用戶訪問(wèn)?在系統(tǒng)訪問(wèn)高峰時(shí)期, 僅從代碼層面提供系統(tǒng)并發(fā)量,系統(tǒng)真的就能夠支持突然流量的沖擊?顯然是不可能的,如果誰(shuí)讓你在不改變硬件配置的情況下,無(wú)限制的提高系統(tǒng)性能,你可以說(shuō)他在白日做夢(mèng)。
簡(jiǎn)介
限流器顧名思義,就是對(duì)流量的限制,準(zhǔn)確的說(shuō)應(yīng)該是流量控制,當(dāng)然并不是無(wú)理由的進(jìn)行流量控制,應(yīng)該是在計(jì)算機(jī)硬件能夠承載的范圍內(nèi),防止系統(tǒng)突然流量過(guò)高導(dǎo)致系統(tǒng)資源耗盡,最終 系統(tǒng)宕機(jī)或崩潰,使得服務(wù)器上的應(yīng)用全部掛掉。限流器是在保證應(yīng)用能夠正常提供服務(wù)的前提下,通過(guò)流量控制實(shí)現(xiàn)對(duì)服務(wù)的一種保護(hù)手段。
當(dāng)然流量的閾值到底是多少比較合適,這個(gè)可能需要根據(jù)實(shí)際硬件配置、系統(tǒng)環(huán)境以前其他相關(guān)參數(shù)經(jīng)過(guò)各種測(cè)試與驗(yàn)證才能知道...
本篇文章僅討論限流中相關(guān)的技術(shù),在實(shí)際應(yīng)用中使用的限流器,除了包含流量限制的作用,為了提高用戶體驗(yàn),還需要對(duì)流量超出是,做出對(duì)應(yīng)的應(yīng)對(duì)策略,比如直接拒絕服務(wù),讓請(qǐng)求進(jìn)行排隊(duì) ,或者服務(wù)降級(jí)都是比較好的處理手段,這樣既能給用戶友好地體驗(yàn),又能保證服務(wù)正常。
核心
有幾個(gè)核心概念需要先了解到:
- 限流的目標(biāo)對(duì)象:請(qǐng)求數(shù)量、網(wǎng)絡(luò)流量、用戶訪問(wèn)次數(shù)...
 - 限流的維度:時(shí)間、IP、用戶
 - 限流的實(shí)現(xiàn)層面:前端頁(yè)面、WEB代理、服務(wù)接口...
 
應(yīng)用場(chǎng)景
- 防止服務(wù)接口短時(shí)間涌入大量請(qǐng)求導(dǎo)致服務(wù)器資源快速耗盡最終服務(wù)無(wú)法訪問(wèn)
 - 突發(fā)流量時(shí)通過(guò)排隊(duì)策略實(shí)現(xiàn)流量削峰,杜絕對(duì)服務(wù)器的沖擊
 - 針對(duì)ip、或用戶控制對(duì)某個(gè)資源的訪問(wèn)次數(shù)
 - 針對(duì)高頻接口,控制單位時(shí)間內(nèi)允許的請(qǐng)求次數(shù)
 - 結(jié)合ip或其他因子防爬蟲
 
限流方法
這里我們主要討論后端基于請(qǐng)求量的限流,限流是一種非常廣泛的應(yīng)用技術(shù),就比如你在登錄系統(tǒng)時(shí),經(jīng)常會(huì)需要你輸入手機(jī)驗(yàn)證、動(dòng)態(tài)碼或一些奇奇怪怪的驗(yàn)證方式, 來(lái)降低登錄請(qǐng)求的頻次。
- 計(jì)數(shù)限流
 
按數(shù)量進(jìn)行控制,達(dá)到設(shè)置的閾值則進(jìn)行限流,其中固定窗口,滑動(dòng)窗口則是通過(guò)該方法實(shí)現(xiàn)。
- 固定窗口
 
通過(guò)控制時(shí)間單元內(nèi)允許的請(qǐng)求數(shù)量,一旦達(dá)到閾值,則不會(huì)處理該請(qǐng)求后續(xù)相關(guān)的業(yè)務(wù)或者直接讓請(qǐng)求快速失敗并給予提示。

比如我們配置10s內(nèi)允許請(qǐng)求的流量為1000,在第1~9s內(nèi)請(qǐng)求為0,在第9~10秒內(nèi)的請(qǐng)求數(shù)為1000,這樣一秒內(nèi)的請(qǐng)求就達(dá)到了1000。當(dāng)然我們可以時(shí)間單元?jiǎng)澐殖筛×6龋?但是應(yīng)該多小才合適呢?
問(wèn)題:只能對(duì)時(shí)間單元內(nèi)的總請(qǐng)求數(shù)進(jìn)行控制,當(dāng)請(qǐng)求集中在較小時(shí)間范圍內(nèi)時(shí),無(wú)法達(dá)到流量限制的效果,因此這是一種粗粒度的流量限制手段
- 滑動(dòng)窗口
 
為了解決固定窗口算法中存在的問(wèn)題,通過(guò)滑動(dòng)窗口的方法,將上述時(shí)間單元?jiǎng)澐殖啥鄠€(gè)細(xì)粒度的時(shí)間窗口,每個(gè)窗口都有自己獨(dú)立的請(qǐng)求計(jì)數(shù)器,這樣就可以讓時(shí)間單元內(nèi)的流量控制均勻地 落在各個(gè)時(shí)間窗口上,同時(shí)滑動(dòng)的時(shí)間窗口可以形成連續(xù)時(shí)間區(qū)間控制,并不像固定窗口那樣只在兩個(gè)時(shí)間刻度間。

比如時(shí)間單元為1s,每個(gè)時(shí)間窗口為100ms,在1秒內(nèi)的10個(gè)時(shí)間窗口可以為09:01:01.000~09:01:02.000、09:01:01.200~09:01:02.800...
問(wèn)題:滑動(dòng)窗口的區(qū)間劃分的越多,則滑動(dòng)窗口的滾動(dòng)就越平滑,限流的統(tǒng)計(jì)就會(huì)越精確,但也需要更多的資源為窗口時(shí)間片段保存計(jì)數(shù)器,從而耗費(fèi)系統(tǒng)資源
- 漏桶算法
 
如果將請(qǐng)求看成水滴,限流器看成一個(gè)下面開口的桶(漏桶)。漏桶算法其實(shí)就是當(dāng)水滴(請(qǐng)求)先進(jìn)入到漏桶里,漏桶以一定的速度出水,當(dāng)水流入速度過(guò)大時(shí)則會(huì)超過(guò)桶的可接納容量, 這時(shí)水將直接溢出,漏桶算法能強(qiáng)行限制數(shù)據(jù)的傳輸速率。使用漏桶算法,可以保證接口會(huì)以一個(gè)常速速率來(lái)處理請(qǐng)求,所以漏桶算法必定不會(huì)出現(xiàn)臨界問(wèn)題。

問(wèn)題:當(dāng)短時(shí)間內(nèi)如果有大量的突發(fā)請(qǐng)求時(shí),即使服務(wù)器負(fù)載不高,每個(gè)請(qǐng)求也需要等待一段時(shí)間(水滴間隔)才能被響應(yīng)
- 令牌桶算法
 
令牌桶算法會(huì)以一個(gè)恒定的速度往桶里放入令牌,而如果請(qǐng)求需要被處理,則需要先從桶里獲取一個(gè)令牌,當(dāng)桶里沒有令牌可取時(shí),則拒絕服務(wù)。相比“漏桶算法”,“令牌桶算法”能夠在限制數(shù)據(jù)的平均傳輸速率的同時(shí),還允許能應(yīng)對(duì)流量突增的情況(允許突發(fā)請(qǐng)求,只要有足夠的令牌,支持一次拿多個(gè)令牌)。

實(shí)現(xiàn)示例
固定窗口
Guava RateLimiter
- 令牌桶算法實(shí)現(xiàn)
 - 支持預(yù)熱
 - 支持突發(fā)流量
 
配置  | 說(shuō)明  | 
permitsPerSecond  | 單位時(shí)間內(nèi)產(chǎn)生令牌數(shù)量  | 
warmupPeriod  | 預(yù)熱期  | 
unit  | 預(yù)熱期時(shí)間單位  | 
創(chuàng)建RateLimiter,每秒發(fā)放6個(gè)令牌,平均間隔167ms一個(gè),其中有3秒的預(yù)熱期
使用RateLimiter
結(jié)果:大約3秒后進(jìn)入平穩(wěn)期
- 預(yù)熱期 系統(tǒng)剛啟動(dòng)或者長(zhǎng)時(shí)間沒有收到請(qǐng)求時(shí),限流器處于冷卻狀態(tài),在預(yù)熱期間獲取令牌的時(shí)間會(huì)比平穩(wěn)期獲取令牌的時(shí)間要長(zhǎng),隨著令牌的減少,獲取單個(gè)令牌的時(shí)間會(huì)慢慢變短,最終到達(dá)一個(gè)穩(wěn)定值
 - acquire acquire是一個(gè)阻塞方法,通過(guò)RateLimiter會(huì)得到一個(gè)阻塞時(shí)間值
 - tryAcquire 非阻塞方法,快速返回令牌申請(qǐng)結(jié)果
 
結(jié)束語(yǔ)
作為微服務(wù)服務(wù)保證的三大利器,限流、熔斷、降級(jí),了解其大概的大概的含義是非常有必要的,雖然現(xiàn)在有很多封裝好的限流框架,比如Sentinel、Resilience4j等,但技術(shù)是沒有止境的,當(dāng)你往下探索 時(shí),更多不可思議的知識(shí),后面有機(jī)會(huì)我們從源碼,更底層來(lái)認(rèn)識(shí)這些技術(shù)與設(shè)計(jì)思想。















 
 
 
















 
 
 
 