帶你快速了解:限流中的漏桶和令牌桶算法
本文轉(zhuǎn)載自微信公眾號「腦子進(jìn)煎魚了」,作者陳煎魚 。轉(zhuǎn)載本文請聯(lián)系腦子進(jìn)煎魚了公眾號。
前言
理論上每一個對外/內(nèi)提供功能的資源點,都需要進(jìn)行一定的流量控制,否則在業(yè)務(wù)的持續(xù)迭代中,是有可能出現(xiàn)突發(fā)性流量的場景(就像年初所帶來的一些行業(yè)突發(fā)轉(zhuǎn)變,導(dǎo)致業(yè)務(wù)流量突然暴增):
突發(fā)流量
若沒有進(jìn)行限流,就會出現(xiàn)一些奇奇怪怪的問題點,實則就是系統(tǒng)無法承受這波流量,逐漸崩潰,走向系統(tǒng)假死。
現(xiàn)實場景
最常見的現(xiàn)實場景就是日常隨處可見的排插、插座,其內(nèi)置的保險絲,也被稱為電流保險絲,其主要是起過載保護(hù)作用,保險絲會在電流異常升高到一定的高度和熱度的時候,自身熔斷切斷電流,從而起到保護(hù)電路安全運行的作用。
因此真實世界中有許多與軟件工程中的限流熔斷的場景有異曲同工之處,也是為了控制量,超量就切斷。你也可以想想現(xiàn)實生活中是否有遇到其他類似的例子呢?
保險絲(圖來自網(wǎng)絡(luò))
漏桶算法(Leaky Bucket)
漏桶算法(Leaky Bucket)是網(wǎng)絡(luò)中流量整形(Traffic Shaping)或速率限制(Rate Limiting)時常用的一種算法,它的主要目的是控制數(shù)據(jù)注入到網(wǎng)絡(luò)的速率,平滑網(wǎng)絡(luò)上的突發(fā)流量。
漏桶算法通過其算法調(diào)控了流量訪問,使得突發(fā)流量可以被整形,去毛刺,變成一個相對緩和,以便為網(wǎng)絡(luò)提供一個穩(wěn)定的流量。
漏桶算法的存儲桶主要由三個參數(shù)定義,分別是:桶的容量、水從桶中流出的速率、桶的初始充滿度。
其核心理念就如字面意思:一個會漏水的桶。
圖片來自 geeksforgeeks
Bursty Flow
在上圖中,水龍頭代表著突發(fā)流量(Bursty Flow)。當(dāng)網(wǎng)絡(luò)中存在突發(fā)流量,且無任何調(diào)控時,就會出現(xiàn)像 Bursty Data 處類似的場景。主機以 12 Mbps 的速率發(fā)送數(shù)據(jù),時間持續(xù) 2s,總計 24 Mbits 數(shù)據(jù)。隨后主機暫停發(fā)送 5s,然后再以 2 Mbps 的速率發(fā)送數(shù)據(jù) 3s,最終總共發(fā)送了 6 Mbits 的數(shù)據(jù)。
因此主機在 10s 內(nèi)總共發(fā)送了 30 Mbits 的數(shù)據(jù)。但這里存在一個問題,就是數(shù)據(jù)的發(fā)送并不是平滑的,存在一個較大的波峰。若所有流量都是如此的傳輸方式,將會 “旱的旱死澇的澇死”,對系統(tǒng)并不是特別的友好。
Fixed Flow
為了解決 Bursty Flow 場景的問題。漏桶(Leaky Bucket)出現(xiàn)了,漏桶具有固定的流出速率、固定的容量大小。
在上圖中,漏桶在相同的 10s 內(nèi)以 3 Mbps 的速率持續(xù)發(fā)送數(shù)據(jù)來平滑流量。若水(流量)來的過猛,但水流(漏水)不夠快時,其最終結(jié)果就是導(dǎo)致水直接溢出,呈現(xiàn)出來就是拒絕請求/排隊等待的表現(xiàn)。另外當(dāng) Buckets 空時,是會出現(xiàn)一次性倒入達(dá)到 Bucket 容量限制的水的可能性,此時也可能會出現(xiàn)波峰。
簡單來講就是,一個漏桶,水流進(jìn)來,但漏桶只有固定的流速來流出水,若容量滿即拒絕,否則將持續(xù)保持流量流出。
令牌桶算法
令牌桶算法也是網(wǎng)絡(luò)中流量整形或速率限制時常用的一種算法,它的主要目的是控制發(fā)送到網(wǎng)絡(luò)上的數(shù)據(jù)的數(shù)目,并允許突發(fā)數(shù)據(jù)的發(fā)送。
令牌桶算法會以一個恒定的速率向桶里放入令牌,如果有新的請求進(jìn)來希望進(jìn)行處理,則必須要先從桶內(nèi)拿到一個可用的令牌,才能繼續(xù)被處理。若桶內(nèi)無令牌可取時,則拒絕請求/排隊等待。
圖片來自 gateoverflow
- 每 1/r 秒新增一個 token 到 buckets 中。
- buckets 中最多可容納 b 個令牌。如果桶已滿,將丟棄這個新增的 token(也就是不需要新的 token)。
- 當(dāng)主機傳輸 n bytes packets 時,buckets 中如果有 n 個令牌,則取到所需令牌,成功傳輸 n bytes。
- 當(dāng)可用的 token 小于 n bytes 時,不會從 buckets 中取到任何 token,本次請求將被拒絕/排隊等待。
漏桶 vs 令牌桶
漏桶算法和令牌桶算法本質(zhì)上都是為了做流量整形(Traffic Shaping)或速率限制(Rate Limiting),避免系統(tǒng)因為大流量而被打崩,但兩者核心差異在于限流的方向是相反的。
令牌桶限制的是流量的平均流入速率,并且允許一定程度的突然性流量,最大速率為桶的容量和生成 token 的速率。而漏桶限制的是流量的流出速率,是相對固定的。
因此也會相對的帶來一個問題,在某些場景中,漏桶算法并不能有效的使用網(wǎng)絡(luò)資源,因為漏桶的漏出速率是相對固定的,所以在網(wǎng)絡(luò)情況比較好,沒有擁塞的狀態(tài)下,漏桶依然是限制住的,并沒有辦法放開量。而令牌桶算法則不同,其能夠是限制平均速率的同時支持一定程度的突發(fā)流量。
總結(jié)
在軟件系統(tǒng)中,限流常常所代表的就是流量整形、速率限制,是一個非常常見的調(diào)控手段。一般我們會將其在初期集成到統(tǒng)一框架、網(wǎng)關(guān)、Mesh 中去。因此建議接觸業(yè)務(wù)的同學(xué),都要對這一塊進(jìn)行考量,便于后續(xù)的快速使用/接入,畢竟業(yè)務(wù)的流量爆發(fā)總是來的比較突然,甚至可能是惡意攻擊。
而本文所提到的漏桶,令牌桶都是非常常見的手段,雖然兩者獨立出來分析了。但從軟件開發(fā)的角度來講,你認(rèn)為兩者是否可以融合,結(jié)合其優(yōu)勢呢?