高并發(fā)中的 限流、熔斷、降級(jí)、預(yù)熱、背壓!
首先,我們需要明確一下這幾個(gè)名詞出現(xiàn)的場(chǎng)景:分布式高并發(fā)環(huán)境。如果你的產(chǎn)品賣相不好,沒人鳥它,那它就用不著這幾個(gè)屬性。不需要任何加成,低并發(fā)系統(tǒng)就能工作的很好。
分布式系統(tǒng)是一個(gè)整體,調(diào)用關(guān)系錯(cuò)綜復(fù)雜,其中某個(gè)資源異常,大概率會(huì)造成級(jí)聯(lián)故障。當(dāng)系統(tǒng)處于超負(fù)荷的壓力之下,容器或者宿主機(jī),將表現(xiàn)的異乎尋常的脆弱。load飆升、拒絕響應(yīng),甚至于雪崩,造成的后果都比較嚴(yán)重。
鑒于分布式系統(tǒng)病嬌娘樣式的反應(yīng),我們有各種手段來處理這些異常狀況。接下來,我們將簡(jiǎn)要介紹一下這些場(chǎng)景,還有常用的手段。
1. 限流
“我的貼子被限流了!” 即使不是互聯(lián)網(wǎng)從業(yè)人員,也能言之鑿鑿的說出這樣的話。當(dāng)他這么說的時(shí)候,他并不是在說高并發(fā)中的限流,它只是邏輯意義上的。
web開發(fā)中,tomcat默認(rèn)是200個(gè)線程池,當(dāng)更多的請(qǐng)求到來,沒有新的線程能夠去處理這個(gè)請(qǐng)求,那這個(gè)請(qǐng)求將會(huì)一直等待在瀏覽器方。表現(xiàn)的形式是,瀏覽器一直在轉(zhuǎn)圈(還沒超過acceptCount),即使你請(qǐng)求的是一個(gè)簡(jiǎn)單的Hello world。
你可以把這個(gè)過程,也看作是限流。它在本質(zhì)上,是設(shè)置一個(gè)資源數(shù)量上限,超出這個(gè)上限的請(qǐng)求,將被緩沖,或者直接失敗。
對(duì)于高并發(fā)場(chǎng)景下的限流來說,它有特殊的含義:它主要是用來保護(hù)底層資源的。如果你想要調(diào)用某些服務(wù),你需要首先獲取調(diào)用它的許可。限流一般由服務(wù)提供方來提供,對(duì)調(diào)用方能夠做事的能力進(jìn)行限制。
比如,某個(gè)服務(wù)為A、B、C都提供了服務(wù),但根據(jù)提前申請(qǐng)的流量預(yù)估,限制A服務(wù)的請(qǐng)求為1000/秒、B服務(wù)2000/秒,C服務(wù)1w/秒。在同一時(shí)刻,某些客戶端可能會(huì)出現(xiàn)被拒絕的請(qǐng)求,而某些客戶端能夠正常運(yùn)行,限流被看作是服務(wù)端的自我保護(hù)能力。
常見的限流算法有:計(jì)數(shù)器、漏桶、令牌桶等。但計(jì)數(shù)器算法無法實(shí)現(xiàn)平滑的限流,在實(shí)際應(yīng)用中使用較少。
2. 熔斷
通常來說,皇帝在微服務(wù)里想夜生活過得舒服,能夠大刀闊斧單刀直入,不因私事丟江山,就不得不靠熔斷大總管。熔斷的作用,主要是為了避免服務(wù)的雪崩。
如圖,A→B→C互相依次調(diào)用,但C項(xiàng)目很可能出現(xiàn)問題(流量過大或者報(bào)錯(cuò)等),就會(huì)引發(fā)線程一直進(jìn)行等待,導(dǎo)致拖垮整個(gè)鏈路層,線程資源耗盡。
意如其名,熔斷就像是保險(xiǎn)絲,超過負(fù)載了保險(xiǎn)絲就燒掉了。當(dāng)然,當(dāng)后端服務(wù)緩和的時(shí)候,我們還可以再把它接上。熔斷功能一般由調(diào)用端提供,用在不太重要的旁路請(qǐng)求上,避免這些不重要的服務(wù)因?yàn)楫惓;蛘叱瑫r(shí),影響正常的、重要的業(yè)務(wù)邏輯
在實(shí)現(xiàn)上,我們可以把熔斷看作是一種代理模式。當(dāng)熔斷打開的時(shí)候,服務(wù)將暫停對(duì)其保護(hù)資源的訪問,并返回固定的或者不產(chǎn)生遠(yuǎn)程調(diào)用的默認(rèn)結(jié)果。
3. 降級(jí)
降級(jí)是一個(gè)比較模糊的說法。限流、熔斷,在一定程度上,也可以看作是降級(jí)的一種。但通常所說的降級(jí),切入的層次更加高級(jí)一些。
降級(jí)一般考慮的是分布式系統(tǒng)的整體性,從源頭上切斷流量的來源。比如在雙11的時(shí)候,為了保證交易系統(tǒng),將會(huì)暫停一些不重要的服務(wù),以免產(chǎn)生資源爭(zhēng)占。服務(wù)降級(jí)有人工參與,人為使得某些服務(wù)不可用,多屬于一種業(yè)務(wù)降級(jí)方式。
在什么地方最適合做降級(jí)呢?就是入口。比如Nginx,比如DNS等。
在某些互聯(lián)網(wǎng)應(yīng)用中,會(huì)存在MVP(Minimum Viable Product)這個(gè)概念,意為最小化可行產(chǎn)品,它的SLA要求非常高。圍繞著最小可行性產(chǎn)品,會(huì)有一系列的服務(wù)拆分操作,當(dāng)然某些情況甚至需要重寫。
比如,一個(gè)電商系統(tǒng),在極端情況下,只需要把商品顯示出來,把商品賣出去就行。其他一些支撐性的系統(tǒng),比如評(píng)論、推薦等,都可以臨時(shí)關(guān)掉。在物理部署和調(diào)用關(guān)系上,就要考慮這些情況。
4. 預(yù)熱
請(qǐng)看下面一種情況。
一個(gè)高并發(fā)環(huán)境下的DB,進(jìn)程死亡后進(jìn)行重啟。由于業(yè)務(wù)處在高峰期間,上游的負(fù)載均衡策略發(fā)生了重分配。剛剛啟動(dòng)的DB瞬間接受了1/3的流量,然后load瘋狂飆升,直至再無響應(yīng)。
原因就是:新啟動(dòng)的DB,各種Cache并沒有準(zhǔn)備完畢,系統(tǒng)狀態(tài)與正常運(yùn)行時(shí)截然不同。可能平常1/10的量,就能夠把它帶入死亡。
同理,一個(gè)剛剛啟動(dòng)的JVM進(jìn)程,由于字節(jié)碼并未被JIT編譯器優(yōu)化,在剛啟動(dòng)的時(shí)候,所有接口的響應(yīng)時(shí)間都比較慢。如果調(diào)用它的負(fù)載均衡組件,并沒有考慮這種剛啟動(dòng)的情況,1/n的流量被正常路由到這個(gè)節(jié)點(diǎn),就很容易出現(xiàn)問題。
所以,我們希望負(fù)載均衡組件,能夠依據(jù)JVM進(jìn)程的啟動(dòng)時(shí)間,動(dòng)態(tài)的慢慢加量,進(jìn)行服務(wù)預(yù)熱,直到達(dá)到正常流量水平。
5. 背壓
考慮一下下面兩種場(chǎng)景:
沒有限流。請(qǐng)求量過高,有多少收多少,極容易造成后端服務(wù)崩潰或者內(nèi)存溢出
傳統(tǒng)限流。你強(qiáng)行規(guī)定了某個(gè)接口最大的承受能力,超出了直接拒絕,但此時(shí)后端服務(wù)是有能力處理這些請(qǐng)求的
如何動(dòng)態(tài)的修改限流的值?這就需要一套機(jī)制。調(diào)用方需要知道被調(diào)用方的處理能力,也就是被調(diào)用方需要擁有反饋的能力。背壓,英文Back Pressure,其實(shí)是一種智能化的限流,指的是一種策略。
背壓思想,被請(qǐng)求方不會(huì)直接將請(qǐng)求端的流量直接丟掉,而是不斷的反饋?zhàn)约旱奶幚砟芰ΑU?qǐng)求端根據(jù)這些反饋,實(shí)時(shí)的調(diào)整自己的發(fā)送頻率。比較典型的場(chǎng)景,就是TCP/IP中使用滑動(dòng)窗口來進(jìn)行流量控制。
反應(yīng)式編程(Reactive)是觀察者模式的集大成者。它們大多使用事件驅(qū)動(dòng),多是非阻塞的彈性應(yīng)用,基于數(shù)據(jù)流進(jìn)行彈性傳遞。在這種場(chǎng)景下,背壓實(shí)現(xiàn)就簡(jiǎn)單的多。
背壓,讓系統(tǒng)更穩(wěn)定,利用率也更高,它本身擁有更高的彈性和智能。
總結(jié)
簡(jiǎn)單總結(jié)一下:
限流 規(guī)定一個(gè)上限,流量超過系統(tǒng)承載能力時(shí),會(huì)直接拒絕服務(wù)
熔斷 不因底層旁路應(yīng)用的故障,造成系統(tǒng)雪崩。欲練此功,必先自宮
降級(jí) 從請(qǐng)求入口,大范圍的滅掉過載請(qǐng)求
預(yù)熱 給系統(tǒng)一些啟動(dòng)預(yù)熱時(shí)間,加載緩存,避免資源死鎖
背壓 被調(diào)用方反饋?zhàn)约旱哪芰o調(diào)用方。溫柔的調(diào)用,需要堅(jiān)實(shí)的溝通
簡(jiǎn)單來講,只要流量不進(jìn)系統(tǒng),什么都好說,降級(jí)是最威猛最霸道的手段;一旦流量進(jìn)入系統(tǒng),就要接受系統(tǒng)內(nèi)一系列規(guī)則的制約,其中限流是最直接的手段,將請(qǐng)求攔在外面。雖然用戶的請(qǐng)求失敗了,但我的系統(tǒng)還能活;沒有熔斷的系統(tǒng)就很兇殘,很容易讓三流功能影響主要功能,所以要在合適的時(shí)候打開它;至于預(yù)熱,不過是在愛情火花前的一系列前戲,直到服務(wù)的巔峰狀態(tài);當(dāng)然,相對(duì)于請(qǐng)求扔出去就不管的模式,如果被調(diào)用方能夠反饋?zhàn)约旱臓顟B(tài),那么請(qǐng)求方就可以根據(jù)需要加大或者縮減馬力,這就是背壓的思想。
這些手段,都是在有限的資源下,有效的處理手段。但如果公司有錢,有彈性處理手段,這些都會(huì)變成輔助手段。畢竟,當(dāng)所有的服務(wù),能夠?qū)⒆约旱臓顟B(tài),反饋到監(jiān)控中心,監(jiān)控中心能夠?qū)崿F(xiàn)彈性擴(kuò)容。只要服務(wù)拆分的滿足水平擴(kuò)展,我們只需要增加實(shí)例就夠了。
作者簡(jiǎn)介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。