限流概念
目的
通過對并發(fā)/請求進(jìn)行限速來保護(hù)系統(tǒng),防止系統(tǒng)過載。
做到有損服務(wù),而不是不服務(wù)。
負(fù)載過高時(shí),優(yōu)先保護(hù)核心服務(wù)或業(yè)務(wù)
限流方式
限流的方式有很多:
QPS:限制每秒的請求數(shù)
并發(fā)數(shù):避免開啟過多線程導(dǎo)致資源耗盡
連接數(shù):限制TCP連接數(shù)
以下指的限流都是指QPS的限制,不涉及并發(fā)數(shù)和連接數(shù)。
限流規(guī)則
限流策略是根據(jù)業(yè)務(wù)特征來設(shè)置的,可以設(shè)置靜態(tài)策略,也可以動(dòng)態(tài)變化的。
規(guī)則包含有:
限流算法
參數(shù),限流閾值
相應(yīng)策略等(處理方式等)
靜態(tài)規(guī)則
限流閾值
服務(wù)端提前做好整個(gè)服務(wù)端鏈路的性能壓測,先了解業(yè)務(wù)特征,需要請求API的QPS,估算好整個(gè)服務(wù)集群的水位及下游水位(下游服務(wù)和相關(guān)存儲等中間件)。服務(wù)端集群的限流閾值建立在壓測的數(shù)據(jù)基礎(chǔ)上。
壓測需要得到的相關(guān)指標(biāo)
服務(wù):對于計(jì)算型服務(wù),需要考慮服務(wù)本身計(jì)算帶來的系統(tǒng)資源消耗
緩存及數(shù)據(jù)庫:需要訪問存儲的服務(wù),需要考慮數(shù)據(jù)庫的負(fù)載
消息隊(duì)列:雖然一般消息隊(duì)列可以用來作為削峰用途,但是有的消息隊(duì)列是作為其他業(yè)務(wù)事務(wù)等用途的,也需要考慮其負(fù)載情況
其他:下游鏈路中涉及到的各種服務(wù)或者中間件,都應(yīng)該考慮到其負(fù)載
需要考慮:
不同API的不同閾值
整個(gè)鏈路涉及到的服務(wù)閾值:如果某個(gè)請求鏈路需要請求10個(gè)服務(wù),則閾值計(jì)算需要考慮這10個(gè)服務(wù)能夠提供給此服務(wù)的流量配額
不同的限流策略有不同的限流閾值
理論上每次API實(shí)現(xiàn)的業(yè)務(wù)邏輯的改變,以及增加、減少API都要進(jìn)行重新壓測,相對比較麻煩
閾值的估算應(yīng)該考慮整個(gè)服務(wù)的安全水位,閾值定義過高則容易產(chǎn)生過載,過低則浪費(fèi)資源
動(dòng)態(tài)規(guī)則
動(dòng)態(tài)規(guī)則的兩種實(shí)現(xiàn):
自適應(yīng):服務(wù)根據(jù)RT,負(fù)載,QPS等等指標(biāo)動(dòng)態(tài)變更限流規(guī)則
外部通知:通過調(diào)用服務(wù)API來通知服務(wù)更新或服務(wù)自己輪詢規(guī)則服務(wù)器
限流閾值
根據(jù)響應(yīng)時(shí)間或在監(jiān)控系統(tǒng)以及服務(wù)治理中心之上根據(jù)服務(wù)及下游的負(fù)載來動(dòng)態(tài)計(jì)算閾值
服務(wù)端限流 vs 客戶端限流 vs 網(wǎng)關(guān)限流
絕大多數(shù)情況下限流都是發(fā)生在服務(wù)端的,因?yàn)楹芏嗲闆r下客戶端的數(shù)量是不確定的。但有時(shí)候?yàn)榱朔乐箚蝹€(gè)客戶端過度使用服務(wù),那么此處可以在客戶端來完成,當(dāng)然在服務(wù)端也可以同時(shí)進(jìn)行。
一般都推薦在服務(wù)端做限流
服務(wù)端限流
服務(wù)在處理請求前,應(yīng)該對請求進(jìn)行限流計(jì)算,防止系統(tǒng)過載。
同時(shí)也要考慮到為不同的業(yè)務(wù)的客戶端提供不同的限流策略,不能因?yàn)槟硞€(gè)業(yè)務(wù)的問題達(dá)到達(dá)到限流閾值而造成其他業(yè)務(wù)無法請求服務(wù)。
服務(wù)端限流優(yōu)點(diǎn)
更好控制整個(gè)服務(wù)的負(fù)載情況:服務(wù)端的限流閾值不會(huì)因?yàn)榭蛻舳藬?shù)量增加或減少而改變
方便對不同上游服務(wù)進(jìn)行不同閾值的限流策略:可以對不同的調(diào)用者進(jìn)行不同的限流配額,也可以給不同業(yè)務(wù)打上不同的tag再根據(jù)tag來限流。
缺點(diǎn)
如果服務(wù)端只針對QPS限流,而不考慮連接數(shù):服務(wù)在建連過程中也會(huì)產(chǎn)生一些資源消耗,而這些壓力往往可能會(huì)成為瓶頸。特別是短連接,不斷的建鏈過程會(huì)產(chǎn)生大量的資源消耗
如果服務(wù)端也針對連接數(shù)進(jìn)行限制:則不好對不同鏈路或服務(wù)進(jìn)行配額區(qū)分。容易造成某個(gè)業(yè)務(wù)或服務(wù)的連接過多而導(dǎo)致其他服務(wù)也被限制
客戶端限流
客戶端調(diào)用下游服務(wù)時(shí),以每個(gè)服務(wù)集群的限流配額對下游服務(wù)進(jìn)行過載保護(hù)。
優(yōu)點(diǎn)
- 達(dá)到閾值不會(huì)請求服務(wù)端,避免服務(wù)端產(chǎn)生額外的資源消耗,如建立連接
缺點(diǎn)
客戶端的數(shù)量的增加或減少需要重新計(jì)算每個(gè)客戶端的限流閾值
客戶端限流可能出現(xiàn)bug,或者客戶端負(fù)載均衡產(chǎn)生傾斜導(dǎo)致限流失效
服務(wù)不同API不同限流閾值:下游服務(wù)較多,而每個(gè)服務(wù)的不同API有不同限流配額,則客戶端的限流較為復(fù)雜
網(wǎng)關(guān)限流
請求通過網(wǎng)關(guān)來請求服務(wù)端,在網(wǎng)關(guān)中對不同服務(wù)及不同的API進(jìn)行限流。
優(yōu)點(diǎn)
能很好的保護(hù)整個(gè)集群的負(fù)載壓力,服務(wù)端數(shù)量增加或減少,則網(wǎng)關(guān)進(jìn)行相應(yīng)的閾值調(diào)整即可
對不同的上游業(yè)務(wù)的服務(wù)設(shè)置不同的限流配額和不同的限流策略
缺點(diǎn)
需要網(wǎng)關(guān)資源
網(wǎng)關(guān)本身高可用性
限流粒度
限流的粒度可以分為:
服務(wù):對服務(wù)所有API進(jìn)行統(tǒng)一的限流策略
API:每個(gè)API會(huì)有不同的請求鏈路,則相應(yīng)會(huì)有不同的限流策略(閾值等)
API參數(shù):很多時(shí)候我們希望能夠?qū)δ硞€(gè)熱點(diǎn)數(shù)據(jù)中訪問頻次最高的 Top K 數(shù)據(jù)進(jìn)行限制。例如:秒殺,大促等場景,不要因?yàn)槟硞€(gè)商品的頻繁訪問引起的限流導(dǎo)致其他商品無法訪問。
服務(wù)粒度
一個(gè)服務(wù)提供一個(gè)統(tǒng)一的限流的策略。
優(yōu)點(diǎn)是非常簡單,但很容易造成限流失效,無法保護(hù)服務(wù)本身及下游。
如:服務(wù)提供兩種API,都是訪問數(shù)據(jù),兩種API的查詢語句并不一致,API1 查詢非常復(fù)雜,數(shù)據(jù)庫安全水位只能提供10/s的TPS,而對于API2,數(shù)據(jù)庫可以提供1000/s的TPS,這種情況下,如果按照服務(wù)粒度進(jìn)行限流,則只能提供10/s QPS的限流閾值。所以是非常不合理的。
API粒度
不同的API進(jìn)行不同的限流策略,這種方式相對復(fù)雜些,但是更為合理,也能很好的保護(hù)服務(wù)。
要考慮幾種情況:
增加或減少API,則限流策略要做相應(yīng)的調(diào)整
API實(shí)現(xiàn)的改變:請求處理實(shí)現(xiàn)變化則可能需要重新對限流閾值進(jìn)行調(diào)整,避免因?yàn)樵黾右恍I(yè)務(wù)邏輯而導(dǎo)致服務(wù)本身或者下游服務(wù)過載。
大多數(shù)情況下,都應(yīng)該進(jìn)行API粒度的限流,這樣才能更好的保護(hù)服務(wù)本身及服務(wù)的下游服務(wù)和中間件,達(dá)到更好的限流效果。
限流的處理方式
如果達(dá)到了流量限制的閾值,一般處理方式有:
直接返回錯(cuò)誤碼:可以返回資源耗盡或者busy等狀態(tài)碼,或者帶backoff的重試
等待及重試:要注意不要超過請求超時(shí)時(shí)間
限流算法
固定窗口算法Fixed window
通過維護(hù)一個(gè)單位時(shí)間內(nèi)的計(jì)數(shù)值,每當(dāng)一個(gè)請求通過時(shí),就將計(jì)數(shù)值加1,當(dāng)計(jì)數(shù)值超過閾值時(shí),就進(jìn)入限流處理流程。如果單位時(shí)間已經(jīng)結(jié)束,則將計(jì)數(shù)器清零,開啟下一輪的計(jì)數(shù)。
這種方式的缺點(diǎn)是:窗口是固定的,會(huì)存在兩個(gè)窗口邊界突發(fā)流量問題。當(dāng)然,取決于窗口的大小,如果足夠小,則這種問題是可以忽略的
如下圖:
時(shí)間窗口為1s,1s的限制閾值是4,如果一個(gè)惡意用戶在1s的最后的最后500毫秒發(fā)送3個(gè)請求,在下一秒的前500毫秒發(fā)送3個(gè)請求,那么實(shí)際在1秒內(nèi)發(fā)送了6個(gè)請求,就超過了流量的限制。
滑動(dòng)窗口算法Sliding window
將時(shí)間窗口在進(jìn)行細(xì)化,分為N個(gè)小窗口,窗口以小窗口為最小滑動(dòng)單位,這樣就可以避免在兩個(gè)時(shí)間窗口之間產(chǎn)生毛刺現(xiàn)象。(當(dāng)然在小窗口之間仍然會(huì)產(chǎn)生毛刺)
令牌桶算法Token Bucket
令牌桶算法是網(wǎng)絡(luò)流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一種算法。
有3個(gè)階段
令牌的產(chǎn)生:以r/s的速率將token放入bucket中,如果bucket中token數(shù)已到達(dá)bucket的容量b,則丟棄token
獲取令牌:在請求處理前從bucket中獲取(移除)一個(gè)令牌,只有獲取到令牌才進(jìn)行處理
無法獲取令牌:當(dāng)bucket中令牌不夠,請求進(jìn)入限流處理流程(阻塞等待或者直接返回失敗,等待應(yīng)該計(jì)算好超時(shí)時(shí)間)
【圖來源于dev.to】
token bucket特點(diǎn)
最常見的單機(jī)限流算法,開源組件很多,使用也簡單
token bucket可以應(yīng)對短時(shí)間的突發(fā)流量。例如:bucket容量為10,速率為2/s,而請求QPS為2/s,那么bucket中有8個(gè)tokens可以用來應(yīng)對突發(fā)流量。
漏桶算法Leaky Bucket
圖左邊a:一個(gè)桶,不斷的倒水進(jìn)來,桶底下有個(gè)洞,按照固定的速率把水漏走,如果水進(jìn)來的速度比漏走的快,桶可能就會(huì)滿了,水就溢出了
圖右邊b:類似于左邊a,將請求放入桶中,以固定的速率從桶中拿出請求進(jìn)行處理,當(dāng)桶滿了,請求將被阻塞或直接拒絕服務(wù)
【圖來源于dev.to】
leaky bucket特點(diǎn)
不能很好應(yīng)付突發(fā)的流量:例如,桶容量為10,請求處理速率為2/s;請求放入桶的速率為2/s,那么可以容納8個(gè)突發(fā)請求放入桶中,其他等待或者丟棄。
桶可以是普通隊(duì)列形式,也可以是優(yōu)先隊(duì)列:優(yōu)先隊(duì)列是很有必要的
放入桶中的請求應(yīng)該計(jì)算好其超時(shí)時(shí)間,如果請求放入桶中到請求被處理,已經(jīng)超過請求的超時(shí)間,則是沒有意義的,反而阻塞了其他請求。
和令牌桶區(qū)別是:令牌桶是固定速率往桶里放令牌,請求來了取走令牌,桶空了,請求阻塞;漏桶是請求來了往桶里放請求,以固定速率取走請求,桶滿了,請求阻塞。令牌桶允許突發(fā)流量,而漏桶是不允許的。
動(dòng)態(tài)限流算法
前面的算法都是以恒定速率進(jìn)行限流的(令牌桶以固定速率將令牌放入桶中,固定和滑動(dòng)窗口限制閾值都是固定的),這種最大的問題就是每次業(yè)務(wù)邏輯變更,都要重新進(jìn)行壓力測試以計(jì)算出最新的閾值。
在TCP擁塞控制算法中,流量發(fā)送速率是跟網(wǎng)絡(luò)環(huán)境相關(guān)的。那其實(shí)服務(wù)的限流也可以根據(jù)服務(wù)處理請求的時(shí)延或負(fù)載等指標(biāo)來進(jìn)行動(dòng)態(tài)調(diào)整。
預(yù)熱期慢啟動(dòng)
類似于TCP的慢啟動(dòng),定義一個(gè)啟動(dòng)時(shí)的限制閾值,在定義的預(yù)熱時(shí)間周期內(nèi)逐步提升限制閾值,直到周期結(jié)束達(dá)到定義的正常值。
這非常適合于服務(wù)本身或其依賴的存儲等需要進(jìn)行預(yù)熱的場景。
可以參考 guava
例如:
以令牌桶為例,開始時(shí)限制閾值為4/s,預(yù)熱時(shí)間為3/s,正常限制閾值為7/s,那么就在3秒內(nèi),將限制閾值每秒增加1最終達(dá)到7/s的閾值。
根據(jù)響應(yīng)時(shí)間
這種方式根據(jù)請求響應(yīng)時(shí)間來實(shí)時(shí)調(diào)整限流的規(guī)則,相對較為合理。
請求響應(yīng)快則平滑調(diào)整增加閾值,響應(yīng)慢則減少閾值,以及定義一個(gè)最大安全閾值。
關(guān)鍵在于如何量化快與慢:
根據(jù)壓測得到服務(wù)的安全水位,估算出最大閾值。
啟動(dòng)時(shí)設(shè)置一個(gè)保守的閾值
與前一個(gè)時(shí)間窗口內(nèi)響應(yīng)時(shí)間比較,比之前快則可以調(diào)高閾值。
那么隨著響應(yīng)時(shí)間的變化,閾值也在不斷的變化中,閾值的范圍在[1, max_value]之間調(diào)整。
基于監(jiān)控系統(tǒng)
如果服務(wù)是消耗CPU資源的計(jì)算型或者消耗IO資源的存儲型等,則基于監(jiān)控系統(tǒng)更為合理。
根據(jù)CPU,load,內(nèi)存,IO等系統(tǒng)指標(biāo)和請求響應(yīng)時(shí)間等業(yè)務(wù)指標(biāo)綜合考慮,隨著監(jiān)控指標(biāo)的變化動(dòng)態(tài)改變限流規(guī)則,這種限流相對較為復(fù)雜,根據(jù)自己業(yè)務(wù)設(shè)計(jì)適合自己的計(jì)算方式。
如果是IO型,則IO指標(biāo)的權(quán)重相對要高一些,如果是計(jì)算型,則CPU和Load要權(quán)重高一些。
分布式限流
單節(jié)點(diǎn)限流最大的問題是當(dāng)服務(wù)節(jié)點(diǎn)動(dòng)態(tài)添加或減少后,每個(gè)服務(wù)的限流配額也要跟隨動(dòng)態(tài)改變。
如果服務(wù)節(jié)點(diǎn)增加了,而原來節(jié)點(diǎn)限流配額沒有減少,則下游服務(wù)就可能過載。
而分布式限流則避免了這種問題,通過像redis集群或發(fā)票服務(wù)器這種取號的方式來限制某個(gè)資源的流量。
redis限流
基于redis的單線程及原子操作特性來實(shí)現(xiàn)限流功能,這種方式可以實(shí)現(xiàn)簡單的分布式限流。但是redis本身也容易成為瓶頸,且redis不管是主從結(jié)構(gòu)還是其cluster模式,都存在主節(jié)點(diǎn)故障問題。
方案1:固定窗口計(jì)數(shù)
將要限制的資源名+時(shí)間窗口為精度的時(shí)間戳 作為redis 的key,設(shè)置略大于時(shí)間戳的超時(shí)時(shí)間,然后用redis的incrby的原子特性來增加計(jì)數(shù)。
如果限流的時(shí)間窗口以秒為單位,則
redis key : 資源名 + unix timestamp
count : incrby key count
expire 2
檢查count是否達(dá)到閾值
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local acquireCount = tonumber(ARGV[2])
local current = tonumber(redis.call('get', key) or "0")
if current + acquireCount > limit then
return 0
else
redis.call("incrby", key, acquireCount)
redis.call("expire", key, "2")
return 1
end
這種方案存在的問題:
要和redis進(jìn)行交互:時(shí)延較差
熱點(diǎn)資源redis容易成為瓶頸
redis進(jìn)行主從切換會(huì)導(dǎo)致限流失效
服務(wù)的時(shí)鐘會(huì)有誤差:由于lua中有寫操作就不能使用帶隨機(jī)性質(zhì)的讀操作所以不能通過redis lua獲取
屬于固定窗口算法,在窗口之間容易產(chǎn)生突發(fā)流量問題
方案2:令牌桶
local function acquire(key, acquireTokens, currentTimeMillSecond)
local rateLimiterInfo = redis.pcall("HMGET", key, "lastTimeMilliSecond", "availableTokens", "maxLimit", "rate")
local lastTimeMilliSecond = rateLimiterInfo[1]
local availableTokens = tonumber(rateLimiterInfo[2])
local maxLimit = tonumber(rateLimiterInfo[3])
local rate = rateLimiterInfo[4]
local currentTokens = availableTokens;
local result = -1
if (type(lastTimeMilliSecond) ~= 'boolean' and lastTimeMilliSecond ~= false and lastTimeMilliSecond ~= nil) then
local diffTime = currentTimeMillSecond - lastTimeMilliSecond
if diffTime > 0 then
local fillTokens = math.floor((diffTime / 1000) * rate)
local allTokens = fillTokens + availableTokens;
currentTokens = math.min(allTokens, maxLimit);
end
end
if (currentTokens - acquireTokens >= 0) then
result = 1
redis.pcall("HMSET", key, "lastTimeMilliSecond", currentTimeMillSecond, "availableTokens", currentTokens - acquireTokens)
end
return result
end
local key = KEYS[1]
local acquireTokens = ARGV[1]
local currentTimeMillSecond = ARGV[2]
local ret = acquire(key, acquireTokens, currentTimeMillSecond)
return ret
這種方案存在的問題:
要和redis進(jìn)行交互:時(shí)延較差
熱點(diǎn)資源redis容易成為瓶頸
redis進(jìn)行主從切換會(huì)導(dǎo)致限流失效
服務(wù)的時(shí)鐘會(huì)有誤差:由于lua中有寫操作就不能使用帶隨機(jī)性質(zhì)的讀操作所以不能通過redis lua獲取
發(fā)票服務(wù)器
上述redis方案,是將redis作為一種發(fā)票服務(wù)器,但是由于redis這種方案本身存在可用性問題(主從切換等),控制規(guī)則也比較簡單,所以對于可用性要求比較高且規(guī)則復(fù)雜的需求,都選擇自己開發(fā)服務(wù)器程序來作為發(fā)票服務(wù)器。
發(fā)票服務(wù)器一般由一些服務(wù)進(jìn)程組成一個(gè)或多個(gè)發(fā)票集群。
而服務(wù)通過RPC向發(fā)票服務(wù)器領(lǐng)票,成功則可以執(zhí)行,否則則進(jìn)入限流機(jī)制。為了減少RPC通信帶來的延遲,一般可以批量獲取。
發(fā)票規(guī)則
發(fā)票規(guī)則(限流算法)可以存儲到一致性存儲或者數(shù)據(jù)庫等,發(fā)票服務(wù)器定期更新或者監(jiān)聽通知來獲取規(guī)則的變化。
也可以通過其他服務(wù)來動(dòng)態(tài)調(diào)整算法和閾值,然后通知發(fā)票服務(wù)器,也可以發(fā)票服務(wù)器自己根據(jù)負(fù)載情況來計(jì)算。
發(fā)票服務(wù)器特點(diǎn):
發(fā)票服務(wù)器可用性高:通過集群模式,且可以持久化到數(shù)據(jù)庫。
發(fā)票服務(wù)器負(fù)載均衡:服務(wù)從發(fā)票服務(wù)集群領(lǐng)票要注意發(fā)票服務(wù)器負(fù)載均衡,避免造成有的發(fā)票服務(wù)器發(fā)票領(lǐng)完有的卻有大量剩余發(fā)票
發(fā)票服務(wù)器高性能:因?yàn)榘l(fā)票服務(wù)器的計(jì)算和存儲都基于內(nèi)存,所以性能不容易成為瓶頸
發(fā)票服務(wù)器一致性:類似于ID生成器,對于極高要求的場景,可以定期將發(fā)票服務(wù)器發(fā)票的信息等進(jìn)行持久化存儲,故障時(shí)再從中進(jìn)行恢復(fù)
微服務(wù)架構(gòu)下限流的難點(diǎn)
在微服務(wù)架構(gòu)下,調(diào)用鏈路很長,服務(wù)的調(diào)用關(guān)系復(fù)雜,上游服務(wù)一個(gè)小的改動(dòng),將影響所有下游服務(wù),還會(huì)產(chǎn)生疊加效應(yīng)。
流控規(guī)則
微服務(wù)架構(gòu)下,固定流控規(guī)則是不合適的,固定規(guī)則往往根據(jù)壓測結(jié)果進(jìn)行計(jì)算得來,而微服務(wù)架構(gòu)下,鏈路上一個(gè)節(jié)點(diǎn)的變化都會(huì)導(dǎo)致固定規(guī)則的失效。
如:
服務(wù)某個(gè)鏈路為 A->B->C->D
而B做了一些業(yè)務(wù)邏輯的變更,那么鏈路就有可能產(chǎn)生變化,導(dǎo)致之前的鏈路壓測結(jié)果不準(zhǔn)確,如果還按照之前的閾值,則可能導(dǎo)致流控失效。
微服務(wù)架構(gòu)下,應(yīng)該采用動(dòng)態(tài)規(guī)則,讓服務(wù)自適應(yīng)或者規(guī)則服務(wù)器來通知服務(wù)改變限流規(guī)則
根據(jù)調(diào)用鏈路的限流規(guī)則
下游服務(wù)進(jìn)行限流時(shí),也要考慮給予上游服務(wù)的流量配額,否則很容易因?yàn)橛捎谀硞€(gè)上游服務(wù)的故障,導(dǎo)致整個(gè)下游鏈路不可用。
如:
鏈路1:A->B->C->D
鏈路2:D->B->C
A如果故障,導(dǎo)致調(diào)用B流量暴漲,那么調(diào)用C的流量也會(huì)暴漲。這個(gè)時(shí)候鏈路2的D服務(wù)則會(huì)收到B或C的流控影響。
所以B和C應(yīng)該根據(jù)給予鏈路1和鏈路2進(jìn)行不同的配額,鏈路1達(dá)到閾值則對鏈路1的調(diào)用進(jìn)行限流,不影響鏈路2的調(diào)用。
考慮調(diào)用鏈路優(yōu)先級
一般微服務(wù)場景會(huì)根據(jù)業(yè)務(wù)來定義其可用性權(quán)重。權(quán)重高的業(yè)務(wù)往往要優(yōu)先保證其可用性。
那么就存在復(fù)雜調(diào)用鏈路上,針對不同業(yè)務(wù)的請求來進(jìn)行限流,服務(wù)壓力過大時(shí),優(yōu)先保證重要的業(yè)務(wù)可運(yùn)行。
如:
鏈路1:A->B->C->D
鏈路2:D->B->C
鏈路1的重要性高于鏈路2,那么如果C的負(fù)載升高時(shí),C就要降低整體的限流閾值,那么就要降低鏈路2的限流閾值,犧牲鏈路2的可用性來保證鏈路1。
所以就需要將鏈路進(jìn)行tag標(biāo)識,服務(wù)C根據(jù)tag來區(qū)分鏈路。
總結(jié)
限流算法往往相對簡單且開源方案很多。而難點(diǎn)在于如何選擇適合自己的限流算法。
不管是單節(jié)點(diǎn)線路還是分布式限流,都有各自的優(yōu)缺點(diǎn),需要根據(jù)自身業(yè)務(wù)特性、規(guī)模以及架構(gòu)復(fù)雜性來選擇適合自己的方案。
微服務(wù)架構(gòu)下,限流變得相當(dāng)復(fù)雜,要考慮清楚各種可能導(dǎo)致限流失效的場景。
博客:https://ikenchina.github.io/
知乎:https://zhuanlan.zhihu.com/p/158948815
C++ 令牌桶的實(shí)現(xiàn)
https://github.com/ikenchina/ratelimit