帶你快速瞭解:限流中的漏桶和令牌桶演算法

EDDYCJY發表於2020-10-17

在前文 《限流熔斷是什麼,怎麼做,不做行不行?》中針對 “限流” 動作,有提到流量控制其內部對應著兩種常用的限流演算法,分別是漏桶演算法和令牌桶演算法。因此會有的讀者會好奇,這都是些啥?

為了更進一步的瞭解 WHY,本文來快速探索一下,看看限流下的一些 “演算法” 們到底有何作用,是為何成為流量控制的基石的?

image

前言

理論上每一個對外/內提供功能的資源點,都需要進行一定的流量控制,否則在業務的持續迭代中,是有可能出現突發性流量的場景(就像年初所帶來的一些行業突發轉變,導致業務流量突然暴增):

image

若沒有進行限流,就會出現一些奇奇怪怪的問題點,實則就是系統無法承受這波流量,逐漸崩潰,走向系統假死。

現實場景

最常見的現實場景就是日常隨處可見的排插、插座,其內建的保險絲,也被稱為電流保險絲,其主要是起過載保護作用,保險絲會在電流異常升高到一定的高度和熱度的時候,自身熔斷切斷電流,從而起到保護電路安全執行的作用。

因此真實世界中有許多與軟體工程中的限流熔斷的場景有異曲同工之處,也是為了控制量,超量就切斷。你也可以想想現實生活中是否有遇到其他類似的例子呢?

image

漏桶演算法(Leaky Bucket)

漏桶演算法(Leaky Bucket)是網路中流量整形(Traffic Shaping)或速率限制(Rate Limiting)時常用的一種演算法,它的主要目的是控制資料注入到網路的速率,平滑網路上的突發流量。

漏桶演算法通過其演算法調控了流量訪問,使得突發流量可以被整形,去毛刺,變成一個相對緩和,以便為網路提供一個穩定的流量。

漏桶演算法的儲存桶主要由三個引數定義,分別是:桶的容量、水從桶中流出的速率、桶的初始充滿度。

其核心理念就如字面意思:一個會漏水的桶。

圖片來自 geeksforgeeks

Bursty Flow

在上圖中,水龍頭代表著突發流量(Bursty Flow)。當網路中存在突發流量,且無任何調控時,就會出現像 Bursty Data 處類似的場景。主機以 12 Mbps 的速率傳送資料,時間持續 2s,總計 24 Mbits 資料。隨後主機暫停傳送 5s,然後再以 2 Mbps 的速率傳送資料 3s,最終總共傳送了 6 Mbits 的資料。

因此主機在 10s 內總共傳送了 30 Mbits 的資料。但這裡存在一個問題,就是資料的傳送並不是平滑的,存在一個較大的波峰。若所有流量都是如此的傳輸方式,將會 “旱的旱死澇的澇死”,對系統並不是特別的友好。

Fixed Flow

為了解決 Bursty Flow 場景的問題。漏桶(Leaky Bucket)出現了,漏桶具有固定的流出速率、固定的容量大小。

在上圖中,漏桶在相同的 10s 內以 3 Mbps 的速率持續傳送資料來平滑流量。若水(流量)來的過猛,但水流(漏水)不夠快時,其最終結果就是導致水直接溢位,呈現出來就是拒絕請求/排隊等待的表現。另外當 Buckets 空時,是會出現一次性倒入達到 Bucket 容量限制的水的可能性,此時也可能會出現波峰。

簡單來講就是,一個漏桶,水流進來,但漏桶只有固定的流速來流出水,若容量滿即拒絕,否則將持續保持流量流出。

令牌桶演算法

令牌桶演算法也是網路中流量整形或速率限制時常用的一種演算法,它的主要目的是控制傳送到網路上的資料的數目,並允許突發資料的傳送。

令牌桶演算法會以一個恆定的速率向桶裡放入令牌,如果有新的請求進來希望進行處理,則必須要先從桶內拿到一個可用的令牌,才能繼續被處理。若桶內無令牌可取時,則拒絕請求/排隊等待。

圖片來自 gateoverflow

  1. 每 1/r 秒新增一個 token 到 buckets 中。

  2. buckets 中最多可容納 b 個令牌。如果桶已滿,將丟棄這個新增的 token(也就是不需要新的 token)。

  3. 當主機傳輸 n bytes packets 時,buckets 中如果有 n 個令牌,則取到所需令牌,成功傳輸 n bytes。

  4. 當可用的 token 小於 n bytes 時,不會從 buckets 中取到任何 token,本次請求將被拒絕/排隊等待。

漏桶 vs 令牌桶

漏桶演算法和令牌桶演算法本質上都是為了做流量整形(Traffic Shaping)或速率限制(Rate Limiting),避免系統因為大流量而被打崩,但兩者核心差異在於限流的方向是相反的。

令牌桶限制的是流量的平均流入速率,並且允許一定程度的突然性流量,最大速率為桶的容量和生成 token 的速率。而漏桶限制的是流量的流出速率,是相對固定的。

因此也會相對的帶來一個問題,在某些場景中,漏桶演算法並不能有效的使用網路資源,因為漏桶的漏出速率是相對固定的,所以在網路情況比較好,沒有擁塞的狀態下,漏桶依然是限制住的,並沒有辦法放開量。而令牌桶演算法則不同,其能夠是限制平均速率的同時支援一定程度的突發流量。

總結

在軟體系統中,限流常常所代表的就是流量整形、速率限制,是一個非常常見的調控手段。一般我們會將其在初期整合到統一框架、閘道器、Mesh 中去。因此建議接觸業務的同學,都要對這一塊進行考量,便於後續的快速使用/接入,畢竟業務的流量爆發總是來的比較突然,甚至可能是惡意攻擊。

而本文所提到的漏桶,令牌桶都是非常常見的手段,雖然兩者獨立出來分析了。但從軟體開發的角度來講,你認為兩者是否可以融合,結合其優勢呢?

我的公眾號

分享 Go 語言、微服務架構和奇怪的系統設計,歡迎大家關注我的公眾號和我進行交流和溝通。

最好的關係是互相成就,各位的點贊就是煎魚創作的最大動力,感謝支援。

更多原創文章乾貨分享,請關注公眾號
  • 帶你快速瞭解:限流中的漏桶和令牌桶演算法
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章