1. 程式人生 > >一個基於使用者的API限流策略 Rate Limit

一個基於使用者的API限流策略 Rate Limit

1. 限流場景

在開發高併發系統時,有很多種方法可用來保護系統:快取、降級、限流等。

  • 快取:提升系統訪問速度,增大系統處理能力
  • 降級:服務出現問題或影響核心流程的效能時,需要暫時遮蔽,待高峰過去或問題解決後再開啟
  • 限流:部分場景比如:稀缺資源(秒殺,搶購)、寫服務(評論、下單)、頻繁複雜查詢(評論最後幾頁)等,需要限制這些場景的併發/請求量

限流就是通過對併發訪問/請求進行限速或一個時間視窗內的請求進行限速,從而達到保護系統的目的。一般系統可以通過壓測來預估能處理的峰值,一旦達到設定的峰值閥值,則可以拒絕服務(定向錯誤頁或告知資源沒有了)、排隊或等待(例如:秒殺、評論、下單)、降級(返回預設資料)

限流不能亂用,否則正常流量會出現一些奇怪的問題,從而導致使用者抱怨。

2. 限流演算法

常見限流演算法:技術器、令牌桶和漏桶演算法。

2.1. 計數器

計數器是最簡單粗暴的演算法。例如:一個服務每秒能處理100個請求。設定一個1s的滑動視窗,視窗有10個格子,每個格子100ms,每100ms移動一次,每次移動都記錄當前服務請求的次數。記憶體中儲存最近10次的次數(LinkedList)。格子每次移動的時候判斷一次,最後一個格子和第一個格子的次數是否相差100,如果超過,則進行限流。

當格子劃分的越多,那麼滑動視窗的滾動越平滑,限流的統計就會越精確。

計數器的實現簡單,但是是平均分配1秒鐘的請求,然而實際情況中的請求往往是動態的,流量不平滑的。

 

2.2. 令牌桶

令牌桶演算法是一個存放固定容量令牌(token)的桶,按照固定速率往桶裡新增令牌。令牌桶的主要概念如下:

  • 令牌按固定的速率被放入令牌桶中,例如:r tokens/秒
  • 桶中最多存放b個令牌,當桶滿時,新新增的令牌被丟棄或拒絕
  • 當一個n位元組大小的資料包到達,將從桶中刪除n個令牌,接著資料包被髮送到網路上
  • 如果桶中的令牌不足n個,則不會刪除令牌,且資料包將被限流(丟棄或在緩衝區等待)

令牌桶根據放令牌的速率(r tokens/s)去控制輸出的速率(to network)

 

令牌桶的另外一個好處是可以方便的改變速度. 一旦需要提高速率,則按需提高放入桶中的令牌的速率. 一般會定時(比如100毫秒)往桶中增加一定數量的令牌, 有些變種演算法則實時的計算應該增加的令牌的數量.

2.3. 漏桶

漏桶( Leaky Bucket )演算法思路很簡單,水(請求)先進入到漏桶裡,漏桶以一定的速度出水(介面有響應速率),當水流入速度過大會直接溢位(訪問頻率超過介面響應速率),然後就拒絕請求,可以看出漏桶演算法能強行限制資料的傳輸速率。

漏桶作為計量工具時,可用於流量整形和流量控制,漏桶的主要概念如下:

  • 一個固定容量的漏桶,按照常量固定速率流出水滴(流出請求)
  • 如果桶是空的,則不需流出水滴
  • 可以以任意速率流入水滴到漏桶(流入請求)
  • 如果流入水滴超出了桶的容量,則流入的水滴溢位了(新流入的請求被拒絕),則漏桶容量是不變的

漏桶可以看做固定容量、固定流出速率的佇列,漏桶限制的是請求的流出速率,漏桶中裝的是請求

因為漏桶的漏出速率是固定的引數,所以,即使網路中不存在資源衝突(沒有發生擁塞),漏桶演算法也不能使流突發( burst )到埠速率.因此,漏桶演算法對於存在突發特性的流量來說缺乏效率.

 

2.4. 令牌桶和漏桶的比較

 

令牌桶

漏桶

請求何時拒絕 固定速率往桶中新增令牌,如果桶中令牌不夠,則拒絕新請求 流入請求速率任意,常量固定速率流出請求。當流入請求數積累到漏桶容量時,則拒絕新請求
速率限制 限制平均流入速率,允許一定程度的突發請求(支援一次拿多個令牌) 限制常量流出速率(流出速率是固定值),從而平滑突發流入速率

 

參考:

基於Redis的限流系統的設計