限流顧名思義是限制流量,限制流量的目的是爲了保障服務穩定運行,避免服務被流量沖垮。當流量超出服務處理能力時,部分請求將會被限流組件攔截。被攔截的請求可能會被丟棄,若是是 C 端請求,那麼這個請求可能會被導向指定的錯誤頁上,而不是生硬的拒絕。這裏咱們丟棄掉一部分請求,以保證大部分請求能夠正常響應。若是咱們不這樣作,那麼服務崩潰後,全部請求都將沒法響應了。當一臺機器崩潰後,該機器的全部流量將由其餘機器承擔,這樣就會形成剩餘機器壓力增大,進而致使奔潰,最後造成雪崩。除此以外,服務崩潰還會形成數據不一致的嚴重問題,特別是一些敏感數據。好比對於電商網站,若是後臺服務準備將某筆訂單數據存入數據庫時,服務忽然崩潰,致使數據沒有落庫。這個時候,開發同窗就要想辦法修訂數據了。git
綜上,咱們能夠看出來限流的重要性。接下來,我將向你們介紹三種經常使用的限流算法,分別是計數器、漏桶算法和令牌桶算法。下面咱們從最簡單的計數器開始提及。github
計數器算法的思想很簡單,每當一個請求到來時,咱們就將計數器加一,當計數器數值超過閾值後,就拒絕餘下請求。一秒鐘後,咱們將計數器清零,開始新一輪的計數。計數器算法簡單粗暴,易於實現。可是缺點也是有的,也就是所謂的"突刺現象"。舉例說明一下,假如咱們給計數器設置的閾值爲100。系統瞬間內(好比10毫秒內)有200個請求到來,這個時候計數器只能放過其中的100個請求,餘下的100個請求所有被拒絕掉。若是第二秒內沒有請求到來,那麼系統就處於空閒狀態。也就是上一秒忙的要死,這一秒又閒的要死。若是咱們能用一個容器將剩餘的100個請求緩存起來,待計數器重置後再將這些請求放出來。這樣系統在這兩秒內的吞吐量就由100變成了200,提高了一倍。基於這個思考,下面咱們再來看看漏桶算法。算法
漏桶算法由流量容器、流量入口和出口組成。其中流量出口流速即爲咱們指望的限速值,好比 100 QPS。漏桶算法除了具有限流能力,還具有流量整型功能。下面咱們經過一張圖來了解漏桶算法。數據庫
圖片出處:未知緩存
如上圖,流入漏桶流量的流速是不恆定的,通過漏桶限速後,流出流量的速度是恆定的。須要說明的是,漏桶的容量是有限的,一旦流入流量超出漏桶容量,這部分流量只能被丟棄了。工具
漏桶是一個比較好的限流整型工具,不過漏桶不能處理突發流量,一些觀點認爲這是它的一個缺點。不過若是較起真來,我以爲這個缺點是不成立的。畢竟漏桶本就是用來平滑流量的,若是支持突發,那麼輸出流量反而不平滑了。若是要找一種可以支持突發流量的限流算法,那麼令牌桶算法能夠知足需求。網站
令牌桶和漏桶很有幾分類似,只不過令牌通裏存放的是令牌。它的運行過程是這樣的,一個令牌工廠按照設定值按期向令牌桶發放令牌。當令牌桶滿了後,多出的令牌會被丟棄掉。每當一個請求到來時,該請求對應的線程會從令牌桶中取令牌。初期因爲令牌桶中存放了不少個令牌,所以容許多個請求同時取令牌。當桶中沒有令牌後,沒法獲取到令牌的請求能夠丟棄,或者重試。下面咱們來看一下的令牌桶示意圖:spa
圖片出處:未知線程
儘管令牌桶容許突發流量,但突發流量速率 R1 + 限流速率 R2 不能超過系統最大的處理能力 Rt,即 R1 + R2 ≤ Rt,不然會沖垮系統。code
以上就是本篇文章的所有內容。本篇文章簡單分析幾種常見限流算法的運行過程,限於能力緣由,文章如有錯誤不妥之處還請指明。除了文字性描述,這裏也把三種算法的簡單實現代碼貼出來 RateLimiter,有興趣的同窗自取。
好了,本篇文章到這裏就結束了,感謝你們的閱讀。
本文在知識共享許可協議 4.0 下發布,轉載需在明顯位置處註明出處
做者:田小波
本文同步發佈在個人我的博客: http://www.tianxiaobo.com
本做品採用知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。