摘要:計數(shù)限流算法無論固定窗口還是滑動窗口核心均是對請求進(jìn)行計數(shù),區(qū)別僅僅在于對于計數(shù)時間區(qū)間的處理。令牌桶限流實現(xiàn)原理令牌桶限流的實現(xiàn)原理在有詳細(xì)說明。因此由此為入口進(jìn)行分析。目前可返回的實現(xiàn)子類包括及兩種,具體不同下文詳細(xì)分析。
限流
限流一詞常用于計算機(jī)網(wǎng)絡(luò)之中,定義如下:
In computer networks, rate limiting is used to control the rate of traffic sent or received by a network interface controller and is used to prevent DoS attacks.
通過控制數(shù)據(jù)的網(wǎng)絡(luò)數(shù)據(jù)的發(fā)送或接收速率來防止可能出現(xiàn)的DOS攻擊。而實際的軟件服務(wù)過程中,限流也可用于API服務(wù)的保護(hù)。由于提供服務(wù)的計算機(jī)資源(包括CPU、內(nèi)存、磁盤及網(wǎng)絡(luò)帶寬等)是有限的,則其提供的API服務(wù)的QPS也是有限的,限流工具就是通過限流算法對API訪問進(jìn)行限制,保證服務(wù)不會超過其能承受的負(fù)載壓力。
本文主要涉及內(nèi)容包括:
常用限流算法的簡單介紹及比較
Guava包中限流工具的實現(xiàn)分析
常用限流算法援引wiki中關(guān)于限流的Algorithms一小節(jié)的說明,常用的限流算法主要包括:
Token bucket-令牌桶
Leaky bucket-漏桶
Fixed window counter-固定窗口計數(shù)
Sliding window log-滑動窗口日志
Sliding window counter-滑動窗口計數(shù)
以上幾種方式其實可以簡單的分為計數(shù)算法、漏桶算法和令牌桶算法。
計數(shù)限流算法無論固定窗口還是滑動窗口核心均是對請求進(jìn)行計數(shù),區(qū)別僅僅在于對于計數(shù)時間區(qū)間的處理。
固定窗口計數(shù) 實現(xiàn)原理固定窗口計數(shù)法思想比較簡單,只需要確定兩個參數(shù):計數(shù)周期T及周期內(nèi)最大訪問(調(diào)用)數(shù)N。請求到達(dá)時使用以下流程進(jìn)行操作:
固定窗口計數(shù)實現(xiàn)簡單,并且只需要記錄上一個周期起始時間與周期內(nèi)訪問總數(shù),幾乎不消耗額外的存儲空間。
算法缺陷固定窗口計數(shù)缺點也非常明顯,在進(jìn)行周期切換時,上一個周期的訪問總數(shù)會立即置為0,這可能導(dǎo)致在進(jìn)行周期切換時可能出現(xiàn)流量突發(fā),如下圖所示
簡化模型,假設(shè)在兩個周期T0中a時刻有n1個訪問同時到達(dá),周期T1中b時刻有n2個訪問同時到達(dá),且n1和n2均小于設(shè)定的最高訪問次數(shù)N(否則會觸發(fā)限流)。
根據(jù)以上假設(shè)可以推斷,限流器不會限流,n1+n2次訪問均可以通過?,F(xiàn)假設(shè)a,b兩時刻之間時間差為t,則可以得出以下關(guān)系:
$$ left{ egin{aligned} n1 le N n2 le N (n1+n2) le 2N end{aligned} ight. $$
根據(jù)觀察可發(fā)現(xiàn),在$t$的時間內(nèi),出現(xiàn)了$n1+n2$次請求,且$n1+n2$是可能大于$N$的,所以在實際使用過程中,固定窗口計數(shù)器存在突破限額N的可能。
舉例,限制QPS為10,某用戶在周期切換的前后的0.1秒內(nèi),分兩次發(fā)送10次請求,根據(jù)算法規(guī)則此20次請求可通過限流器,則0.1面秒請求數(shù)20,超過每秒最多10次請求的限制。
為解決固定窗口計數(shù)帶來的周期切換處流量突發(fā)問題,可以使用滑動窗口計數(shù)。滑動窗口計算本質(zhì)上也是固定窗口計數(shù),區(qū)別在于將計數(shù)周期進(jìn)行細(xì)化。
實現(xiàn)原理滑動窗口計數(shù)法與股固定窗口計數(shù)法相比較,除了計數(shù)周期T及周期內(nèi)最大訪問(調(diào)用)數(shù)N兩個參數(shù),增加一個參數(shù)M,用于設(shè)置周期T內(nèi)的滑動窗口數(shù)。限流流程如下:
滑動窗口計數(shù)在固定窗口計數(shù)記錄數(shù)據(jù)基礎(chǔ)上,需要增加一個長度為M的計數(shù)數(shù)組,用于記錄在窗口滑動過程中各窗口訪問數(shù)據(jù)。其流程示例如下:
周期切換問題滑動窗口針對周期進(jìn)行了細(xì)分,不存在周期到后計數(shù)直接重置為0的情況,故不會出現(xiàn)跨周期的流量限制問題。
非計數(shù)限流法 漏桶限流 實現(xiàn)原理漏桶限流算法的實現(xiàn)原理在wiki有詳細(xì)說明,引用其原理圖:
簡單說明為:人為設(shè)定漏桶流出速度及漏桶的總?cè)萘?,在請求到達(dá)時判斷當(dāng)前漏桶容量是否已滿,不滿則可將請求存入桶中,否則拋棄請求。程序以設(shè)定的速率取出請求進(jìn)行處理。
根據(jù)描述,需要確定參數(shù)為漏桶流出速度r及漏桶容量N,流程如下:
漏桶算法主要特點在于可以保證無論收到請求的速率如何,真正抵達(dá)服務(wù)方接口的請求速率最大為r,能夠?qū)斎氲恼埱筮M(jìn)行平滑處理。
漏桶算法的缺點也非常明顯,由于其只能以特定速率處理請求,則如何確定該速率就是核心問題,如果速率設(shè)置太小則會浪費性能資源,設(shè)置太大則會造成資源不足。并且由于速率的設(shè)置,無論輸入速率如何波動,均不會體現(xiàn)在服務(wù)端,即使資源有空余,對于突發(fā)請求也無法及時處理,故對有突發(fā)請求處理需求時,不宜選擇該方法。
令牌桶限流的實現(xiàn)原理在wiki有詳細(xì)說明。簡單總結(jié)為:設(shè)定令牌桶中添加令牌的速率,并且設(shè)置桶中最大可存儲的令牌,當(dāng)請求到達(dá)時,向桶中請求令牌(根據(jù)應(yīng)用需求,可能為1個或多個),若令牌數(shù)量滿足要求,則刪除對應(yīng)數(shù)量的令牌并通過當(dāng)前請求,若桶中令牌數(shù)不足則觸發(fā)限流規(guī)則。
根據(jù)描述需要設(shè)置的參數(shù)為,令牌添加速率r,令牌桶中最大容量N,流程如下:
令牌桶算法通過設(shè)置令牌放入速率可以控制請求通過的平均速度,且由于設(shè)置的容量為N的桶對令牌進(jìn)行緩存,可以容忍一定流量的突發(fā)。
算法比較以上提到四種算法,本小節(jié)主要對四種算法做簡單比較算法進(jìn)行對比。
算法名稱 | 需要確定參數(shù) | 實現(xiàn)簡介 | 空間復(fù)雜度 | 說明 |
---|---|---|---|---|
固定窗口計數(shù) | 計數(shù)周期T 周期內(nèi)最大訪問數(shù)N |
使用計數(shù)器在周期內(nèi)累加訪問次數(shù),達(dá)到最大次數(shù)后出發(fā)限流策略 | O(1),僅需要記錄周期內(nèi)訪問次數(shù)及周期開始時間 | 周期切換時可能出現(xiàn)訪問次數(shù)超過限定值 |
滑動窗口計數(shù) | 計數(shù)周期T 周期內(nèi)最大訪問數(shù)N 滑動窗口數(shù)M |
將時間周期分為M個小周期,分別記錄每個小周期內(nèi)訪問次數(shù),并且根據(jù)時間滑動刪除過期的小周期 | O(M),需要記錄每個小周期中的訪問數(shù)量 | 解決固定窗口算法周期切換時的訪問突發(fā)問題 |
漏桶算法 | 漏桶流出速度r 漏桶容量N |
服務(wù)到達(dá)時直接放入漏桶,如當(dāng)前容量達(dá)到N,則觸發(fā)限流側(cè)率,程序以r的速度在漏桶中獲取訪問請求,知道漏桶為空 | O(1),僅需要記錄當(dāng)前漏桶中容量 | 平滑流量,保證服務(wù)請求到達(dá)服務(wù)方的速度恒定 |
令牌桶算法 | 令牌產(chǎn)生速度r 令牌桶容量N |
程序以r的速度向令牌桶中增加令牌,直到令牌桶滿,請求到達(dá)時向令牌桶請求令牌,如有滿足需求的令牌則通過請求,否則觸發(fā)限流策略 | O(1),僅需要記錄當(dāng)前令牌桶中令牌數(shù) | 能夠在限流的基礎(chǔ)上,處理一定量的突發(fā)請求 |
上文簡單介紹了常用的限流算法,在JAVA軟件開發(fā)過程中可使用Guava包中的限流工具進(jìn)行服務(wù)限流。Guava包中限流工具類圖如下所示:
其中RateLimiter類為限流的核心類,其為public的抽象類,RateLimiter有一個實現(xiàn)類SmoothRateLimiter,根據(jù)不同消耗令牌的策略SmoothRateLimiter又有兩個具體實現(xiàn)類SmoothBursty和SmoothWarmingUp。
在實際使用過程中一般直接使用RateLimiter類,其他類對用戶是透明的。RateLimiter類的設(shè)計使用了類似BUILDER模式的小技巧,并做了一定的調(diào)整。
通過RateLimiter類圖可見,RateLimiter類不僅承擔(dān)了具體實現(xiàn)類的創(chuàng)建職責(zé),同時也確定了被創(chuàng)建出的實際類可提供的方法。標(biāo)準(zhǔn)創(chuàng)建者模式UML圖如下所示(引用自百度百科)
RateLimiter類即承擔(dān)了builder的職責(zé),也承擔(dān)了Product的職責(zé)。
在實際的代碼編寫過程中,對GUAVA包限流工具的使用參考以下代碼:
final RateLimiter rateLimiter = RateLimiter.create(2.0); // rate is "2 permits per second" void submitTasks(Listtasks, Executor executor) { for (Runnable task : tasks) { rateLimiter.acquire(); // may wait executor.execute(task); } }
以上代碼摘自GUAVA包RateLimiter類的說明文檔,首先使用create函數(shù)創(chuàng)建限流器,指定每秒生成2個令牌,在需要調(diào)用服務(wù)時使用acquire函數(shù)或取令牌。
RateLimiter實現(xiàn)分析根據(jù)代碼示例,抽象類RateLimiter由于承擔(dān)了Product的職責(zé),其已經(jīng)確定了暴露給編程人員使用的API函數(shù),其中主要實現(xiàn)的核心函數(shù)為create及acquire。因此由此為入口進(jìn)行分析。
create函數(shù)分析create函數(shù)具有兩個個重載,根據(jù)不同的重載可能創(chuàng)建不同的RateLimiter具體實現(xiàn)子類。目前可返回的實現(xiàn)子類包括SmoothBursty及SmoothWarmingUp兩種,具體不同下文詳細(xì)分析。
acquire函數(shù)分析acquire函數(shù)也具有兩個重載類,但分析過程僅僅需要關(guān)系具有整形參數(shù)的函數(shù)重載即可,無參數(shù)的函數(shù)僅僅是acquire(1)的簡便寫法。
在acquire(int permits)函數(shù)中主要完成三件事:
預(yù)分配授權(quán)數(shù)量,此函數(shù)返回需要等待的時間,可能為0;
根據(jù)等待時間進(jìn)行休眠;
以秒為單位,返回獲取授權(quán)消耗的時間。
完成以上工作的過程中,RateLimiter類確定了獲取授權(quán)的過程骨架并且實現(xiàn)了一些通用的方法,這些通用方法中會調(diào)用為實現(xiàn)的抽象方法,開發(fā)人員根據(jù)不同的算法需求可實現(xiàn)特定子類對抽象方法進(jìn)行覆蓋。其調(diào)用流程如下圖:
其中橙色塊中reserveEarliestAvailable方法即為需要子類進(jìn)行實現(xiàn)的,下文以該函數(shù)為核心,分析RateLimiter類的子類是如何實現(xiàn)該方法的。
根據(jù)上文的類圖可見,RateLimiter類在GUAVA包中的直接子類僅有SmoothRateLimiter,故以reserveEarliestAvailable函數(shù)為入口研究其具體實現(xiàn),而在代碼實現(xiàn)的過程中需要使用SmoothRateLimiter類中的屬性,現(xiàn)將類中各屬性羅列出來:
序號 | 屬性名稱 | 屬性說明 | 是否為靜態(tài)屬性 |
---|---|---|---|
1 | storedPermits | 當(dāng)前令牌桶中令牌數(shù) | 否 |
2 | maxPermits | 令牌桶中最大令牌數(shù) | 否 |
3 | stableIntervalMicros | 兩個令牌產(chǎn)生的時間間隔 | 否 |
4 | nextFreeTicketMicros | 下一次有空閑令牌產(chǎn)生的時刻 | 否 |
reserveEarliestAvailable源碼如下:
@Override final long reserveEarliestAvailable(int requiredPermits, long nowMicros) { resync(nowMicros); long returnValue = nextFreeTicketMicros; double storedPermitsToSpend = min(requiredPermits, this.storedPermits); double freshPermits = requiredPermits - storedPermitsToSpend; long waitMicros = storedPermitsToWaitTime(this.storedPermits, storedPermitsToSpend) + (long) (freshPermits * stableIntervalMicros); this.nextFreeTicketMicros = LongMath.saturatedAdd(nextFreeTicketMicros, waitMicros); this.storedPermits -= storedPermitsToSpend; return returnValue; }
通過reserveEarliestAvailable的函數(shù)名稱可以知道,該函數(shù)能夠返回令牌可用的最早時間。函數(shù)需要的輸入?yún)?shù)有需求的令牌數(shù)requiredPermits,當(dāng)前時刻nowMicros。進(jìn)入函數(shù)后,首先調(diào)用名為resync的函數(shù):
void resync(long nowMicros) { // if nextFreeTicket is in the past, resync to now if (nowMicros > nextFreeTicketMicros) { double newPermits = (nowMicros - nextFreeTicketMicros) / coolDownIntervalMicros(); storedPermits = min(maxPermits, storedPermits + newPermits); nextFreeTicketMicros = nowMicros; } }
函數(shù)邏輯比較簡單,首先獲取nextFreeTicketMicros,該值在上表中已經(jīng)說明,表示下一次有空閑令牌產(chǎn)生的時刻,如果當(dāng)前時刻小于等于nextFreeTicketMicros,說明在當(dāng)前時刻不可能有新的令牌產(chǎn)生,則直接返回。若當(dāng)前時刻大于nextFreeTicketMicros,則完成以下工作:
計算到當(dāng)前時刻新產(chǎn)生的令牌數(shù),其中涉及一個名為coolDownIntervalMicros 的函數(shù),該函數(shù)返回創(chuàng)建一個新令牌需要的冷卻時間(注:該函數(shù)在當(dāng)前類中并未實現(xiàn),具體實現(xiàn)下文說明);
更新storedPermits屬性,取產(chǎn)生的令牌和最大可存儲令牌之間的最小值;
將nextFreeTicketMicros屬性置為當(dāng)前時刻。
可見,resync函數(shù)主要功能在于計算新產(chǎn)生的令牌數(shù),并更新nextFreeTicketMicros屬性,nextFreeTicketMicros屬性取值是當(dāng)前時刻和nextFreeTicketMicros屬性的原始值中最大的一個。
完成resync函數(shù)的調(diào)用后,使用returnValue變量記錄更新令牌后的最近可用時間(即上文更新后的nextFreeTicketMicros屬性)。
使用storedPermitsToSpend變量記錄需要消耗以存儲的令牌數(shù),其取值為請求令牌數(shù)和當(dāng)前存儲令牌數(shù)之間的最小值。
使用freshPermits變量記錄需要刷新的令牌數(shù),其實現(xiàn)是用需求的令牌數(shù)減去之前計算的storedPermitsToSpend變量,可見freshPermits變量取值為需求令牌數(shù)與已存儲令牌數(shù)之間的差值,當(dāng)需求令牌數(shù)小于已存儲令牌數(shù)是則為0。
后續(xù)為該函數(shù)核心,計算需要等待的時間,計算等待時間主要分為兩個部分:消耗已經(jīng)存儲的令牌需要的時間及生成新令牌的時間,其中storedPermitsToWaitTime函數(shù)用于計算消耗已經(jīng)存儲的令牌需要的時間,該函數(shù)也是抽象函數(shù),后文具體分析子類實現(xiàn)。
完成等待時間的計算后,程序更新nextFreeTicketMicros屬性,將最近可用時間與需要等待的時間相加。
最后在更新存儲的令牌數(shù),將需要消耗額令牌數(shù)減去。
根據(jù)以上的代碼分析可以發(fā)現(xiàn),GUAVA對于令牌桶的實現(xiàn)跟理論有一點點小的區(qū)別。其當(dāng)前一次的請求消耗的令牌數(shù)并不會影響本次請求的等待時間,而是會影響下一次請求的等待時間。
根據(jù)以上分析,當(dāng)一次請求到達(dá),最近可用時間返回當(dāng)前時間和上一次請求計算的最近可用時間的最大值,而本次請求需要的令牌數(shù)會更新下一次的最近可用時間。在這樣的設(shè)計下,如果每秒產(chǎn)生一個令牌,第一請求需求10個令牌,則當(dāng)?shù)谝淮握埱笳{(diào)用acquire方法時能夠立即返回,而下一次請求(無論需要多少令牌)均需要等待到第一個請求之后的10秒以后,第三次請求等待時間則取決于第二次需求了多少令牌。這也是函數(shù)名稱中“reserve”的含義。
在以上文代碼分析中出現(xiàn)了兩個抽象函數(shù)coolDownIntervalMicros及storedPermitsToWaitTime,現(xiàn)分析這兩個抽象函數(shù)。
coolDownIntervalMicros函數(shù)coolDownIntervalMicros函數(shù)在代碼中已經(jīng)有說明:
Returns the number of microseconds during cool down that we have to wait to get a new permit.
主要含義為生成一個令牌需要消耗的時間,該函數(shù)主要應(yīng)用于計算當(dāng)前時間可產(chǎn)生的令牌數(shù)。根據(jù)上文的UML圖SmoothRateLimiter類有兩個子類SmoothBursty及SmoothWarmingUp。
SmoothBursty類中對于coolDownIntervalMicros函數(shù)的實現(xiàn)如下:
@Override double coolDownIntervalMicros() { return stableIntervalMicros; }
可見實現(xiàn)非常簡單,僅僅只是返回stableIntervalMicros屬性,即產(chǎn)生兩個令牌需要的時間間隔。
SmoothWarmingUp類中對于coolDownIntervalMicros函數(shù)的實現(xiàn)如下:
@Override double coolDownIntervalMicros() { return warmupPeriodMicros / maxPermits; }
其中maxPermits屬性上文已經(jīng)出現(xiàn)過,表示當(dāng)前令牌桶的最大容量。warmupPeriodMicros屬性屬于SmoothWarmingUp類的特有屬性,表示令牌桶中令牌從0到maxPermits需要經(jīng)過的時間,故warmupPeriodMicros / maxPermits表示在令牌數(shù)量達(dá)到maxPermits之前的令牌產(chǎn)生時間間隔。
storedPermitsToWaitTime函數(shù)storedPermitsToWaitTime函數(shù)在代碼中已經(jīng)有說明:
Translates a specified portion of our currently stored permits which we want to spend/acquire, into a throttling time. Conceptually, this evaluates the integral of the underlying function we use, for the range of [(storedPermits - permitsToTake), storedPermits]
主要表示消耗存儲在令牌桶中的令牌需要的時間。
SmoothBursty類中對于storedPermitsToWaitTime函數(shù)的實現(xiàn)如下:
@Override long storedPermitsToWaitTime(double storedPermits, double permitsToTake) { return 0L; }
直接返回0,表示消耗令牌不需要時間。
SmoothBursty類中對于storedPermitsToWaitTime函數(shù)的實現(xiàn)如下:
@Override long storedPermitsToWaitTime(double storedPermits, double permitsToTake) { double availablePermitsAboveThreshold = storedPermits - thresholdPermits; long micros = 0; // measuring the integral on the right part of the function (the climbing line) if (availablePermitsAboveThreshold > 0.0) { double permitsAboveThresholdToTake = min(availablePermitsAboveThreshold, permitsToTake); // TODO(cpovirk): Figure out a good name for this variable. double length = permitsToTime(availablePermitsAboveThreshold) + permitsToTime(availablePermitsAboveThreshold - permitsAboveThresholdToTake); micros = (long) (permitsAboveThresholdToTake * length / 2.0); permitsToTake -= permitsAboveThresholdToTake; } // measuring the integral on the left part of the function (the horizontal line) micros += (long) (stableIntervalMicros * permitsToTake); return micros; }
實現(xiàn)較為復(fù)雜,其核心思想在于計算消耗當(dāng)前存儲令牌時需要根據(jù)預(yù)熱設(shè)置區(qū)別對待。其中涉及到新變量thresholdPermits,該變量為令牌閾值,當(dāng)當(dāng)前存儲的令牌數(shù)大于該值時,消耗(storedPermits-thresholdPermits)范圍的令牌需要有預(yù)熱的過程(即消耗每個令牌的間隔時間慢慢減?。?,而消耗0~thresholdPermits個數(shù)的以存儲令牌,每個令牌消耗時間為固定值,即stableIntervalMicros。
而thresholdPermits取值需要考慮預(yù)熱時間及令牌產(chǎn)生速度兩個屬性,即thresholdPermits = 0.5 * warmupPeriodMicros / stableIntervalMicros;。可見閾值為預(yù)熱時間中能夠產(chǎn)生的令牌數(shù)的一半,并且根據(jù)注釋計算消耗閾值以上的令牌的時間可以轉(zhuǎn)換為計算預(yù)熱圖的梯形面積(實際為積分),本處不詳細(xì)展開。
使用此種設(shè)計可以保證在上次請求間隔時間較長時,令牌桶中存儲了較多的令牌,當(dāng)消耗這些令牌時,最開始的令牌消耗時間較長,后續(xù)時間慢慢縮短直到達(dá)到stableIntervalMicros的狀態(tài),產(chǎn)生預(yù)熱的效果。
以上分析GUAVA限流器實現(xiàn),其使用了兩個抽象類及兩個具體子類完成了限流器實現(xiàn),其中使用頂層抽象類承擔(dān)了創(chuàng)建者角色,將所有子類進(jìn)行了透明化,減少了程序員在使用工具過程中需要了解的類的數(shù)量。
在實現(xiàn)限流器的過程中,基于令牌桶的思想,并且增加了帶有預(yù)熱器的令牌桶限流器實現(xiàn)。被限流的線程使用其自帶的SleepingStopwatch工具類,最終使用的是Thread.sleep(ms, ns);方法,而線程使用sleep休眠時其持有的鎖并不會釋放,在多線程編程時此處需要注意。
最后,GUAVA的限流器觸發(fā)算法采用的是預(yù)定令牌的方式,即當(dāng)前請求需要的令牌數(shù)不會對當(dāng)前請求的等待時間造成影響,而是會影響下一次請求的等待時間。
本文主要總結(jié)了當(dāng)前常用的服務(wù)限流算法,對比個各算法特點,最后分析GUAVA包中對于限流器的實現(xiàn)的核心方法。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76971.html
摘要:令牌桶算法對于很多應(yīng)用場景來說,除了要求能夠限制數(shù)據(jù)的平均傳輸速率外,還要求允許某種程度的突發(fā)傳輸。使用以及源碼解析開源工具包提供了限流工具類,該類基于令牌桶算法實現(xiàn)流量限制,使用十分方便,而且十分高效。 前言 在開發(fā)高并發(fā)系統(tǒng)時有三把利器用來保護(hù)系統(tǒng):緩存、降級和限流 緩存 緩存的目的是提升系統(tǒng)訪問速度和增大系統(tǒng)處理容量 降級 降級是當(dāng)服務(wù)出現(xiàn)問題或者影響到核心流程時,需要暫時...
摘要:令牌桶算法漏桶算法漏桶漏桶的出水速度是恒定的,那么意味著如果瞬時大流量的話,將有大部分請求被丟棄掉也就是所謂的溢出。 工作中對外提供的API 接口設(shè)計都要考慮限流,如果不考慮限流,會成系統(tǒng)的連鎖反應(yīng),輕者響應(yīng)緩慢,重者系統(tǒng)宕機(jī),整個業(yè)務(wù)線崩潰,如何應(yīng)對這種情況呢,我們可以對請求進(jìn)行引流或者直接拒絕等操作,保持系統(tǒng)的可用性和穩(wěn)定性,防止因流量暴增而導(dǎo)致的系統(tǒng)運行緩慢或宕機(jī)。 在開發(fā)高并發(fā)...
摘要:自定義注解實現(xiàn)基于接口限流仔細(xì)看會發(fā)現(xiàn)上面的簡單實現(xiàn)會造成我每個接口都要寫一次限流方法代碼很冗余所以采用來使用自定義注解來實現(xiàn)。 服務(wù)限流 -- 自定義注解基于RateLimiter實現(xiàn)接口限流 令牌桶限流算法showImg(https://segmentfault.com/img/bVbgTi6?w=2420&h=1547);圖片來自網(wǎng)上 令牌桶會以一個恒定的速率向固定容量大小桶...
摘要:下面是幾種常見的限流技術(shù)一限流算法常用的限流算法有令牌桶,漏桶令牌桶令牌桶算法是網(wǎng)絡(luò)流量整形和速率限制中最常使用的一種算法。 就秒殺接口來說,當(dāng)訪問頻率或者并發(fā)請求超過其承受范圍的時候,這時候我們就要考慮限流來保證接口的可用性,以防止非預(yù)期的請求對系統(tǒng)壓力過大而引起的系統(tǒng)癱瘓。通常的策略就是拒絕多余的訪問,或者讓多余的訪問排隊等待服務(wù)。下面是幾種常見的限流技術(shù) 一、限流算法常用的限流算...
閱讀 748·2021-11-11 16:54
閱讀 3069·2021-09-26 09:55
閱讀 2022·2021-09-07 10:20
閱讀 1213·2019-08-30 10:58
閱讀 1059·2019-08-28 18:04
閱讀 710·2019-08-26 13:57
閱讀 3601·2019-08-26 13:45
閱讀 1166·2019-08-26 11:42