国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

分布式系統(tǒng)關(guān)注點——想通關(guān)「限流」?只要這一篇

CollinPeng / 1965人閱讀

摘要:之前有了解到哥的一部分讀者們沒有充分搞清楚限流和熔斷的關(guān)系。后者表示系統(tǒng)在同一時刻能處理的最大請求數(shù)量,比如次的并發(fā)。后續(xù)限流策略需要設(shè)定的具體標(biāo)準(zhǔn)數(shù)值就是從這些指標(biāo)中來的。限流閾值不繼續(xù)處理請求。

如果這是第二次看到我的文章,歡迎掃描文末二維碼訂閱我喲~
本文長度為2869字,建議閱讀8分鐘。
可能你在網(wǎng)上看過不少「限流」相關(guān)的文章,但是z哥的這篇可能是最全面,最深入淺出的一篇了(容我飄幾秒~)。
開個玩笑,希望你能收獲一些增量價值就好~。

之前有了解到z哥的一部分讀者們沒有充分搞清楚「限流」和「熔斷」的關(guān)系。我們先來思考一個問題,生活中也有限流,為什么國慶春節(jié)長假熱門景點要限流?而不是一早先開幾小時,如果人多了就關(guān)幾小時,人少了就再開呢?其實這就是限流和熔斷表象上的一個區(qū)別。

在上一篇中我們聊到了「熔斷」(分布式系統(tǒng)關(guān)注點——99%的人都能看懂的「熔斷」以及最佳實踐),有熔斷機(jī)制的系統(tǒng),它對可用性的作用至少保證了不會全盤崩潰。

但是你可以想象一個稍微極端一點的場景,如果系統(tǒng)流量不是很穩(wěn)定,導(dǎo)致頻繁觸發(fā)熔斷的話,是不是意味著系統(tǒng)一直熔斷的三種狀態(tài)中不斷切換。

導(dǎo)致的結(jié)果是每次從開啟熔斷到關(guān)閉熔斷的期間,必然會導(dǎo)致大量的用戶無法正常使用。系統(tǒng)層面的可用性大致是這樣的。

另外,從資源利用率上也會很容易發(fā)現(xiàn),波谷的這段時期資源是未充分利用的。

由此可見,光有熔斷是遠(yuǎn)遠(yuǎn)不夠的。

在高壓下,只要系統(tǒng)沒宕機(jī),如果能將接收的流量持續(xù)保持在高位,但又不超過系統(tǒng)所能承載的上限,會是更有效率的運作模式,因為會將這里的波谷填滿。

在如今的互聯(lián)網(wǎng)已經(jīng)作為社會基礎(chǔ)設(shè)施的大環(huán)境下,上面的這個場景其實離我們并不是那么遠(yuǎn),同時也會顯得沒那么極端。例如,層出不窮的營銷玩法,一個接著一個的社會熱點,以及互聯(lián)網(wǎng)冰山之下的黑產(chǎn)、刷子的蓬勃發(fā)展,更加使得這個場景變的那么的需要去考慮、去顧忌。因為隨時都有可能會涌入超出你預(yù)期的流量,然后壓垮你的系統(tǒng)。

那么限流的作用就很顯而易見了:只要系統(tǒng)沒宕機(jī),系統(tǒng)只是因為資源不夠,而無法應(yīng)對大量的請求,為了保證有限的系統(tǒng)資源能夠提供最大化的服務(wù)能力,因而對系統(tǒng)按照預(yù)設(shè)的規(guī)則進(jìn)行流量(輸出或輸入)限制的一種方法,確保被接收的流量不會超過系統(tǒng)所能承載的上限。

一、怎么做「限流」

從前面聊到的內(nèi)容中我們也知道,限流最好能“限”在一個系統(tǒng)處理能力的上限附近,所以:

通過「壓力測試」等方式獲得系統(tǒng)的能力上限在哪個水平是第一步。

其次,就是制定干預(yù)流量的策略。比如標(biāo)準(zhǔn)該怎么定、是否只注重結(jié)果還是也要注重過程的平滑性等。

最后,就是處理“被干預(yù)掉”的流量。能不能直接丟棄?不能的話該如何處理?

獲得系統(tǒng)能力的上限

第一步不是我們這次內(nèi)容的重點,說起來就是對系統(tǒng)做一輪壓測??梢栽谝粋€獨立的環(huán)境進(jìn)行,也可以直接在生產(chǎn)環(huán)境的多個節(jié)點中選擇一個節(jié)點作為樣本來壓測,當(dāng)然需要做好與其他節(jié)點的隔離。

一般我們做壓測為了獲得2個結(jié)果,「速率」和「并發(fā)數(shù)」。前者表示在一個時間單位內(nèi)能夠處理的請求數(shù)量,比如xxx次請求/秒。后者表示系統(tǒng)在同一時刻能處理的最大請求數(shù)量,比如xxx次的并發(fā)。從指標(biāo)上需要獲得「最大值」、「平均值」或者「中位數(shù)」。后續(xù)限流策略需要設(shè)定的具體標(biāo)準(zhǔn)數(shù)值就是從這些指標(biāo)中來的。

題外話:從精益求精的角度來說,其他的諸如cpu、網(wǎng)絡(luò)帶寬以及內(nèi)存的耗用也可以作為參照因素。
制定干預(yù)流量的策略

常用的策略就4種,我給它起了一個簡單的定義——「兩窗兩桶」。兩窗就是:固定窗口、滑動窗口,兩桶就是:漏桶、令牌桶。

固定窗口

固定窗口就是定義一個“固定”的統(tǒng)計周期,比如1分鐘或者30秒、10秒這樣。然后在每個周期統(tǒng)計當(dāng)前周期中被接收到的請求數(shù)量,經(jīng)過計數(shù)器累加后如果達(dá)到設(shè)定的閾值就觸發(fā)「流量干預(yù)」。直到進(jìn)入下一個周期后,計數(shù)器清零,流量接收恢復(fù)正常狀態(tài)。

這個策略最簡單,寫起代碼來也沒幾行。

全局變量 int totalCount = 0;  //有一個「固定周期」會觸發(fā)的定時器將數(shù)值清零。

if(totalCount > 限流閾值) {
return; //不繼續(xù)處理請求。
}
totalCount++;

// do something...

固定窗口有一點需要注意的是,假如請求的進(jìn)入非常集中,那么所設(shè)定的「限流閾值」等同于你需要承受的最大并發(fā)數(shù)。所以,如果需要顧忌到并發(fā)問題,那么這里的「固定周期」設(shè)定的要盡可能的短。因為,這樣的話「限流閾值」的數(shù)值就可以相應(yīng)的減小。甚至,限流閾值就可以直接用并發(fā)數(shù)來指定。比如,假設(shè)固定周期是3秒,那么這里的閾值就可以設(shè)定為「平均并發(fā)數(shù)*3」。

不過不管怎么設(shè)定,固定窗口永遠(yuǎn)存在的缺點是:由于流量的進(jìn)入往往都不是一個恒定的值,所以一旦流量進(jìn)入速度有所波動,要么計數(shù)器會被提前計滿,導(dǎo)致這個周期內(nèi)剩下時間段的請求被“限制”。要么就是計數(shù)器計不滿,也就是「限流閾值」設(shè)定的過大,導(dǎo)致資源無法充分利用。

「滑動窗口」可以改善這個問題。

滑動窗口
滑動窗口其實就是對固定窗口做了進(jìn)一步的細(xì)分,將原先的粒度切的更細(xì),比如1分鐘的固定窗口切分為60個1秒的滑動窗口。然后統(tǒng)計的時間范圍隨著時間的推移同步后移。

同時,我們還可以得出一個結(jié)論是:如果固定窗口的「固定周期」已經(jīng)很小了,那么使用滑動窗口的意義也就沒有了。舉個例子,現(xiàn)在的固定窗口周期已經(jīng)是1秒了,再切分到毫秒級別能反而得不償失,會帶來巨大的性能和資源損耗。

滑動窗口大致的代碼邏輯是這樣:

全局?jǐn)?shù)組 鏈表[]  counterList = new 鏈表[切分的滑動窗口數(shù)量];
//有一個定時器,在每一次統(tǒng)計時間段起點需要變化的時候就將索引0位置的元素移除,并在末端追加一個新元素。

int sum = counterList.Sum();
if(sum > 限流閾值) {
return; //不繼續(xù)處理請求。
}
int 當(dāng)前索引 = 當(dāng)前時間的秒數(shù) % 切分的滑動窗口數(shù)量;
counterList[當(dāng)前索引]++;

// do something...

雖然說滑動窗口可以改善這個問題,但是本質(zhì)上還是預(yù)先劃定時間片的方式,屬于一種“預(yù)測”,意味著幾乎肯定無法做到100%的物盡其用。

但是,「桶」模式可以做的更好,因為「桶」模式中多了一個緩沖區(qū)(桶本身)。

漏桶

首先聊聊「漏桶」吧。漏桶模式的核心是固定“出口”的速率,不管進(jìn)來多少量,出去的速率一直是這么多。如果涌入的量多到桶都裝不下了,那么就進(jìn)行「流量干預(yù)」。

整個實現(xiàn)過程我們來分解一下。

控制流出的速率。這個其實可以使用前面提到的兩個“窗口”的思路來實現(xiàn)。如果當(dāng)前速率小于閾值則直接處理請求,否則不直接處理請求,進(jìn)入緩沖區(qū),并增加當(dāng)前水位。

緩沖的實現(xiàn)可以做一個短暫的休眠或者記錄到一個容器中再做異步的重試。

最后控制桶中的水位不超過最大水位。這個很簡單,就是一個全局計數(shù)器,進(jìn)行加加減減。

這樣一來,你會發(fā)現(xiàn)本質(zhì)就是:通過一個緩沖區(qū)將不平滑的流量“整形”成平滑的(高于均值的流量暫存下來補(bǔ)足到低于均值的時期),以此最大化計算處理資源的利用率

實現(xiàn)代碼的簡化表示如下:

全局變量 int unitSpeed;  //出口當(dāng)前的流出速率。每隔一個速率計算周期(比如1秒)會觸發(fā)定時器將數(shù)值清零。
全局變量 int waterLevel; //當(dāng)前緩沖區(qū)的水位線。

if(unitSpeed < 速率閾值) {
unitSpeed++;

//do something...
}
else{
if(waterLevel > 水位閾值){
return; //不繼續(xù)處理請求。
}
waterLevel++;
while(unitSpeed >= 速率閾值){
sleep(一小段時間)。
}
unitSpeed++;
waterLevel--;

//do something...
}

更優(yōu)秀的「漏桶」策略已經(jīng)可以在流量的總量充足的情況下發(fā)揮你所預(yù)期的100%處理能力,但這還不是極致。

你應(yīng)該知道,一個程序所在的運行環(huán)境中,往往不單單只有這個程序本身,會存在一些系統(tǒng)進(jìn)程甚至是其它的用戶進(jìn)程。也就是說,程序本身的處理能力是會被干擾的,是會變化的。所以,你可以預(yù)估某一個階段內(nèi)的平均值、中位數(shù),但無法預(yù)估具體某一個時刻的程序處理能力。又因此,你必然會使用相對悲觀的標(biāo)準(zhǔn)去作為閾值,防止程序超負(fù)荷。

那么從資源利用率來說,有沒有更優(yōu)秀的方案呢?有,這就是「令牌桶」。

令牌桶

令牌桶模式的核心是固定“進(jìn)口”速率。先拿到令牌,再處理請求,拿不到令牌就被「流量干預(yù)」。因此,當(dāng)大量的流量進(jìn)入時,只要令牌的生成速度大于等于請求被處理的速度,那么此刻的程序處理能力就是極限

也來分解一下它的實現(xiàn)過程。

控制令牌生成的速率,并放入桶中。這個其實就是多帶帶一個線程在不斷的生成令牌。

控制桶中待領(lǐng)取的令牌水位不超過最大水位。這個和「漏桶」一樣,就是一個全局計數(shù)器,進(jìn)行加加減減。

大致的代碼簡化表示如下(看上去像「固定窗口」的反向邏輯):

全局變量 int tokenCount = 令牌數(shù)閾值; //可用令牌數(shù)。有一個獨立的線程用固定的頻率增加這個數(shù)值,但不大于「令牌數(shù)閾值」。

if(tokenCount == 0){
return; //不繼續(xù)處理請求。
}

tokenCount--;

//do something...

聰明的你可能也會想到,這樣一來令牌桶的容量大小理論上就是程序需要支撐的最大并發(fā)數(shù)。的確如此,假設(shè)同一時刻進(jìn)入的流量將令牌取完,但是程序來不及處理,將會導(dǎo)致事故發(fā)生。

所以,沒有真正完美的策略,只有合適的策略。因此,根據(jù)不同的場景能夠識別什么是最合適的策略是更需要鍛煉的能力。下面z哥分享一些我個人的經(jīng)驗。

二、做「限流」的最佳實踐 四種策略該如何選擇?

首先,固定窗口。一般來說,如非時間緊迫,不建議選擇這個方案,太過生硬。但是,為了能快速止損眼前的問題可以作為臨時應(yīng)急的方案。

其次,滑動窗口。這個方案適用于對異常結(jié)果「高容忍」的場景,畢竟相比“兩窗”少了一個緩沖區(qū)。但是,勝在實現(xiàn)簡單。

然后,漏桶。z哥覺得這個方案最適合作為一個通用方案。雖說資源的利用率上不是極致,但是「寬進(jìn)嚴(yán)出」的思路在保護(hù)系統(tǒng)的同時還留有一些余地,使得它的適用場景更廣。

最后,令牌桶。當(dāng)你需要盡可能的壓榨程序的性能(此時桶的最大容量必然會大于等于程序的最大并發(fā)能力),并且所處的場景流量進(jìn)入波動不是很大(不至于一瞬間取完令牌,壓垮后端系統(tǒng))。

分布式系統(tǒng)中帶來的新挑戰(zhàn)

一個成熟的分布式系統(tǒng)大致是這樣的。

每一個上游系統(tǒng)都可以理解為是其下游系統(tǒng)的客戶端。然后我們回想一下前面的內(nèi)容,可能你發(fā)現(xiàn)了,前面聊的「限流」都沒有提到到底是在客戶端做限流還是服務(wù)端做,甚至看起來更傾向是建立在服務(wù)端的基礎(chǔ)上做。但是你知道,在一個分布式系統(tǒng)中,一個服務(wù)端本身就可能存在多個副本,并且還會提供給多個客戶端調(diào)用,甚至其自身也會作為客戶端角色。那么,在如此交錯復(fù)雜的一個環(huán)境中,該如何下手做限流呢?我的思路是通過「一縱一橫」來考量。

都知道「限流」是一個保護(hù)措施,那么可以將它想象成一個盾牌。另外,一個請求在系統(tǒng)中的處理過程是鏈?zhǔn)降?。那么,正如古時候軍隊打仗一樣,盾牌兵除了有小部分在老大周圍保護(hù),剩下的全在最前線。因為盾的位置越前,能受益的范圍越大。

分布式系統(tǒng)中最前面的是什么?接入層。如果你的系統(tǒng)有接入層,比如用nginx做的反向代理。那么可以通過它的ngx_http_limit_conn_module以及ngx_http_limit_req_module來做限流,是很成熟的一個解決方案。

如果沒有接入層,那么只能在應(yīng)用層以AOP的思路去做了。但是,由于應(yīng)用是分散的,出于成本考慮你需要針對性的去做限流。比如ToC的應(yīng)用必然比ToB的應(yīng)用更需要做,高頻的緩存系統(tǒng)必然比低頻的報表系統(tǒng)更需要做,Web應(yīng)用由于存在Filter的機(jī)制做起來必然比Service應(yīng)用更方便。

那么應(yīng)用間的限流到底是做到客戶端還是服務(wù)端呢?

z哥的觀點是,從效果上客戶端模式肯定是優(yōu)于服務(wù)端模式的,因為當(dāng)處于被限流狀態(tài)的時候,客戶端模式連建立連接的動作都省了。另一個潛在的好處是,與集中式的服務(wù)端模式相比,可以把少數(shù)的服務(wù)端程序的壓力分散掉。但是在客戶端做成本也更高,因為它是去中心化的,假如需要多個節(jié)點之間的數(shù)據(jù)共通的話,是一個很麻煩的事情。

所以,最終z哥建議你:如果考慮成本就服務(wù)端模式,考慮效果就客戶端模式。當(dāng)然也不是絕對,比如一個服務(wù)端的流量大部分都來源于某一個客戶端,那么就可以直接在這個客戶端做限流,這也不失為一個好方案。

數(shù)據(jù)庫層面的話,一般連接字符串中本身就會包含「最大連接數(shù)」的概念,就可以起到限流的作用。如果想做更精細(xì)的控制就只能做到統(tǒng)一封裝的數(shù)據(jù)庫訪問層框架中了。

聊完了「縱」,那么「橫」是什么呢?

不管是多個客戶端,還是同一個服務(wù)端的多個副本。每個節(jié)點的性能必然會存在差異,如何設(shè)立合適的閾值?以及如何讓策略的變更盡可能快的在集群中的多個節(jié)點生效?說起來很簡單,引入一個性能監(jiān)控平臺和配置中心。但這些真真要做好不容易,后續(xù)我們再展開這塊內(nèi)容。

三、總結(jié)

限流就好比保險絲,根據(jù)你制定的標(biāo)準(zhǔn),達(dá)到了就拉閘。

不過,觸發(fā)限流后的措施除了直接丟棄請求之外,還有一個方式是「降級」,那么降級有哪些方式呢?我們下一篇再聊吧。


Question:
你在工作中有遇到過什么場景需要做「限流」嗎?歡迎分享交流一下

相關(guān)文章:

分布式系統(tǒng)關(guān)注點——99%的人都能看懂的「熔斷」以及最佳實踐

分布式系統(tǒng)關(guān)注點——僅需這一篇,吃透「負(fù)載均衡」妥妥的

? 關(guān)于作者:張帆(Zachary,個人微信號:Zachary-ZF)。堅持用心打磨每一篇高質(zhì)量原創(chuàng)。本文首發(fā)于公眾號:「跨界架構(gòu)師」(ID:Zachary_ZF)。

如果你是初級程序員,想提升但不知道如何下手。又或者做程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關(guān)注我的公眾號「跨界架構(gòu)師」,回復(fù)「技術(shù)」,送你一份我長期收集和整理的思維導(dǎo)圖。

如果你是運營,面對不斷變化的市場束手無策。又或者想了解主流的運營策略,以豐富自己的“倉庫”。歡迎關(guān)注我的公眾號「跨界架構(gòu)師」,回復(fù)「運營」,送你一份我長期收集和整理的思維導(dǎo)圖。

定期發(fā)表原創(chuàng)內(nèi)容:架構(gòu)設(shè)計丨分布式系統(tǒng)丨產(chǎn)品丨運營丨一些深度思考。
掃碼加入小圈子 ↓

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/72625.html

相關(guān)文章

  • 讓你的系統(tǒng)“堅挺不倒”的最后一個大招——「降級」

    摘要:常見的降級方案表現(xiàn)形式無非以下三種類型。的級別最低最先可以被降級掉。一旦當(dāng)系統(tǒng)壓力過大的時候,先把級別的功能降級掉。降級實現(xiàn)首先要制定觸發(fā)機(jī)制。將耗時的數(shù)據(jù)落盤操作降級為異步進(jìn)行。 如果這是第二次看到我的文章,歡迎掃描文末二維碼訂閱我喲~本文長度為4069字,建議閱讀11分鐘。 也許你對降級已經(jīng)有了一些認(rèn)識,認(rèn)真看完,我想這篇文章可能會給你帶來一些新的收獲~ 前面兩篇我們已經(jīng)聊過了「熔...

    jindong 評論0 收藏0
  • 布式系統(tǒng)關(guān)注點(19)——深入淺出「異步」

    摘要:如果你對異步的了解比較模糊的話,這次可以帶你一次性深入淺出。同步異步任何事物都是有利有弊的。這也導(dǎo)致了在異步環(huán)境下做事務(wù)的成本更高。但是,異步在跨進(jìn)程通訊中更合適抽象成事件來進(jìn)行協(xié)作。 如果第二次看到我的文章,歡迎「文末」掃碼訂閱我個人的公眾號(跨界架構(gòu)師)喲~?每周五早8點 按時送達(dá)到公眾號。當(dāng)然了,也會時不時加個餐~ Z哥在前面的三篇文章里和你一起聊了「高性能」主題下與「緩存」...

    BicycleWarrior 評論0 收藏0
  • 【備戰(zhàn)春招/秋招系列】Java程序員必備書單

    摘要:相關(guān)推薦,豆瓣評分,人評價本書介紹了在編程中條極具實用價值的經(jīng)驗規(guī)則,這些經(jīng)驗規(guī)則涵蓋了大多數(shù)開發(fā)人員每天所面臨的問題的解決方案。實戰(zhàn)高并發(fā)程序設(shè)計推薦豆瓣評分,書的質(zhì)量沒的說,推薦大家好好看一下。 該文已加入開源文檔:JavaGuide(一份涵蓋大部分Java程序員所需要掌握的核心知識)。地址:https://github.com/Snailclimb... 【強(qiáng)烈推薦!非廣告!】...

    saucxs 評論0 收藏0
  • 一份最中肯的Java學(xué)習(xí)路線+資源分享(拒絕傻逼式分享)

    摘要:因為某些原因,不方便在這里直接發(fā)送百度鏈接,關(guān)注我的微信公眾號面試通關(guān)手冊回復(fù)資源分享第一波即可領(lǐng)取。然后大家還有什么問題的話,可以在我的微信公眾號后臺面試通關(guān)手冊給我說或者加我微信,我會根據(jù)自己的學(xué)習(xí)經(jīng)驗給了說一下自己的看法。 這是一篇針對Java初學(xué)者,或者說在Java學(xué)習(xí)路線上出了一些問題(不知道該學(xué)什么、不知道整體的學(xué)習(xí)路線是什么樣的) 第一步:Java基礎(chǔ)(一個月左右) 推薦...

    hearaway 評論0 收藏0

發(fā)表評論

0條評論

CollinPeng

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<