先來描述一下什么是限流
限流可以認為服務降級的一種,限流就是限制系統的輸入和輸出流量已達到保護系統的目的。一般來說系統的吞吐量是可以被測算的,為了保證系統的穩定運行,一旦達到的需要限制的閾值,就需要限制流量並采取一些措施以完成限制流量的目的。比如:延遲處理,拒絕處理,或者部分拒絕處理等等。
一般做接口限流主要是為了應對突發流量,避免突發流量拖垮服務。如下面一些場景就有可能發生突發流量
- 微博熱搜
- 惡意刷單
- 惡意爬蟲
- 促銷活動
- 防止DOS攻擊
首先是計算器方式實現
計數器又分固定窗口和滑動窗口
固定窗口計數器:
就是一個計算器,就是在一個時鍾周期(該周期也是可以設置的)內,設定一個訪問閾值(就是在剛剛設置的時鍾周期內的並發量)。如果並發量超過訪問閾值,則開始限流
存在的問題
限流不均勻,如下所示我們規定10S內至多10個訪問量,但2S內實際上有20個訪問量。
出現流量尖峰。
滑動窗口計數器:
固定窗口計數器算法由於其存在的臨界問題(尖峰問題),統計的精度過低,可能在時間窗口的重置節點處接收大量流量,為解決這個問題,我們引入了滑動窗口算法。
如下圖,我們規定訪問閾值10,時鍾周期是5秒,5秒內超過10次訪問量開始限流。該思想就是在任何一個5S內都只有10次訪問量。
很明顯,當滑動窗口的格子划分的越多,那么滑動窗口的滾動就越平滑,限流的統計就會越精確。
缺點:
- 不能解決請求分布不均的問題,即無法平滑流量
- 實現更復雜,需要維護時間窗口,占用內存更多,計算時間復雜度也相應變大。
令牌算法:
按照固定的速率往漏斗里添加水,(核心思想是所有請求需要再令牌桶獲取到令牌才可以處理, 同時有一個服務勻速的往令牌桶裝令牌。可以滿足一定的突發請求處理,如果超過令牌桶的請求,也會被拒絕)
過程:
- 一直放令牌,如果令牌桶達到上限則丟棄令牌,假設每秒放10個
- 可以應對一定程度的流量激增,如此時令牌桶有100個令牌,突然發生200次調用,則此時最開始的100次請求可以正常調用,后續的請求才會以10個/s的速率來調用
優點:
- 解決了固定窗口流量尖峰的問題,確保在任意時刻,過去窗口時間內的請求不會超出閾值。
- 可以有效平滑流量,因為令牌桶的令牌是勻速放入的
- 相對滑動窗口更節省內存
- 適合電商搶購或者微博出現熱點事件這種場景,因為在限流的同時可以應對一定的突發流量。如果采用漏桶那樣的均勻速度處理請求的算法,在發生熱點時間的時候,會造成大量的用戶無法訪問, 對用戶體驗的損害比較大。
漏桶算法:
就像一個漏斗,上面口大,下面口小,上面可以一直加很多水的水,但是下面小口的口徑是固定的,只會有固定單位的水通過。而且上面水量過大,漏斗放不下 會溢出丟失
將水和訪問量換一下,就明白了 (核心思想就是請求收到后,會先進入漏斗,然后再按照限定速度請求服務,及可以達到限流的目的,也可以保證后台收到的請求都是平穩的。 但是也有一個缺點,就是突然流量的時候,會導致處理時間太長。當然流量更大的時候會被拒絕,這個是正常的)。
優點:實現相對簡單,可以限制服務請求速率,並且穩定在一個常速。
缺點:對於特發流量處理效率過低,在沒有到達服務器負載閾值,也只能串行處理請求。
實現;限制隊列的大小