阿里P8架构师谈:流量高峰时期的性能瓶颈有哪些、以及如何来解决
 在高并發(fā)大量用戶(hù)的場(chǎng)景,系統(tǒng)一般會(huì)面臨如下三個(gè)挑戰(zhàn):
 
1. 日益增長(zhǎng)的用戶(hù)數(shù)量
2. 日漸復(fù)雜的業(yè)務(wù)
3. 急劇膨脹的數(shù)據(jù)
這些挑戰(zhàn)對(duì)于性能優(yōu)化而言表現(xiàn)為:在保持和降低系統(tǒng)TP95響應(yīng)時(shí)間(指的是將一段時(shí)間內(nèi)的請(qǐng)求響應(yīng)時(shí)間從低到高排序,高于95%請(qǐng)求響應(yīng)時(shí)間的下確界)的前提下,不斷提高系統(tǒng)吞吐量,提升流量高峰時(shí)期的服務(wù)可用性。
本文主要目標(biāo)是為類(lèi)似的場(chǎng)景提供優(yōu)化方案,確保系統(tǒng)在流量高峰時(shí)期的快速響應(yīng)和高可用。
 性能瓶頸場(chǎng)景
 
在講解如何性能優(yōu)化之前,有必要先了解下性能瓶頸在哪里,以下我們先從瓶頸(各種性能堵塞場(chǎng)景)講起,明確問(wèn)題所在,然后我們?cè)俑鶕?jù)瓶頸,來(lái)看如何來(lái)解決方案。
1.長(zhǎng)請(qǐng)求擁塞瓶頸
這是一種單次請(qǐng)求時(shí)延變長(zhǎng)而導(dǎo)致系統(tǒng)性能惡化甚至崩潰的惡化模式。
對(duì)于多線(xiàn)程服務(wù),大量請(qǐng)求時(shí)間變長(zhǎng)會(huì)使線(xiàn)程堆積、內(nèi)存使用增加,最終可能會(huì)通過(guò)如下三種方式之一惡化系統(tǒng)性能:
- 線(xiàn)程數(shù)目變多導(dǎo)致線(xiàn)程之間CPU資源使用沖突,反過(guò)來(lái)進(jìn)一步延長(zhǎng)了單次請(qǐng)求時(shí)間;
- 線(xiàn)程數(shù)量增多以及線(xiàn)程中緩存變大,內(nèi)存消耗隨之劇增,對(duì)于基于Java語(yǔ)言的服務(wù)而言,又會(huì)更頻繁地full GC,反過(guò)來(lái)單次請(qǐng)求時(shí)間會(huì)變得更長(zhǎng);
- 內(nèi)存使用增多,會(huì)使操作系統(tǒng)內(nèi)存不足,必須使用Swap,可能導(dǎo)致服務(wù)徹底崩潰。
- 典型惡化流程圖如下圖:
長(zhǎng)請(qǐng)求擁塞反模式所導(dǎo)致的性能惡化現(xiàn)象非常普遍,所以識(shí)別該模式非常重要。
典型的場(chǎng)景如下:某復(fù)雜業(yè)務(wù)系統(tǒng)依賴(lài)于多個(gè)服務(wù),其中某個(gè)服務(wù)的響應(yīng)時(shí)間變長(zhǎng),隨之系統(tǒng)整體響應(yīng)時(shí)間變長(zhǎng),進(jìn)而出現(xiàn)CPU、內(nèi)存、Swap報(bào)警,在分布式環(huán)境下,從而引起連鎖反應(yīng),最后造成雪崩的情況。阿里P8架構(gòu)師談:什么是緩存雪崩?服務(wù)器雪崩的場(chǎng)景與解決方案
系統(tǒng)進(jìn)入長(zhǎng)請(qǐng)求擁塞反模式的典型標(biāo)識(shí)包括:被依賴(lài)服務(wù)可用性變低、響應(yīng)時(shí)間變長(zhǎng)、服務(wù)的某段計(jì)算邏輯時(shí)間變長(zhǎng)等。
2.多次請(qǐng)求杠桿造成性能瓶頸
客戶(hù)端一次用戶(hù)點(diǎn)擊行為往往會(huì)觸發(fā)多次服務(wù)端請(qǐng)求,這是一次請(qǐng)求杠桿。
每個(gè)服務(wù)端請(qǐng)求進(jìn)而觸發(fā)多個(gè)更底層服務(wù)的請(qǐng)求,這是第二次請(qǐng)求杠桿。每一層請(qǐng)求可能導(dǎo)致一次請(qǐng)求杠桿,請(qǐng)求層級(jí)越多,杠桿效應(yīng)就越大。
在多次請(qǐng)求杠桿反模式下運(yùn)行的分布式系統(tǒng),處于深層次的服務(wù)需要處理大量請(qǐng)求,容易會(huì)成為系統(tǒng)瓶頸。
與此同時(shí),大量請(qǐng)求也會(huì)給網(wǎng)絡(luò)帶來(lái)巨大壓力,特別是對(duì)于單次請(qǐng)求數(shù)據(jù)量很大的情況,網(wǎng)絡(luò)可能會(huì)成為系統(tǒng)徹底崩潰的導(dǎo)火索。典型惡化流程圖如下圖:
多次請(qǐng)求杠桿所導(dǎo)致的性能惡化現(xiàn)象非常常見(jiàn)。
例如:對(duì)于推薦系統(tǒng),一個(gè)用戶(hù)列表請(qǐng)求會(huì)有多個(gè)算法參與,每個(gè)算法會(huì)召回多個(gè)列表單元(商家或者團(tuán)購(gòu)),每個(gè)列表單元有多種屬性和特征,而這些屬性和特征數(shù)據(jù)服務(wù)又分布在不同服務(wù)和機(jī)器上面,所以客戶(hù)端的一次用戶(hù)展現(xiàn)可能導(dǎo)致了成千上萬(wàn)的最底層服務(wù)調(diào)用。
對(duì)于存在多次請(qǐng)求杠桿反模式的分布式系統(tǒng),性能惡化與流量之間往往遵循指數(shù)曲線(xiàn)關(guān)系。這意味著,在平常流量下正常運(yùn)行服務(wù)系統(tǒng),在流量高峰時(shí)通過(guò)線(xiàn)性增加機(jī)器解決不了可用性問(wèn)題。所以,識(shí)別并避免系統(tǒng)進(jìn)入多次請(qǐng)求杠桿反模式對(duì)于提高系統(tǒng)可用性而言非常關(guān)鍵。
3.反復(fù)緩存造成性能瓶頸
為了降低響應(yīng)時(shí)間,系統(tǒng)往往在本地內(nèi)存中緩存很多數(shù)據(jù)。緩存數(shù)據(jù)越多,命中率就越高,平均響應(yīng)時(shí)間就越快。為了降低平均響應(yīng)時(shí)間,有些開(kāi)發(fā)者會(huì)不加限制地緩存各種數(shù)據(jù),在正常流量情況下,系統(tǒng)響應(yīng)時(shí)間和吞吐量都有很大改進(jìn)。
但是當(dāng)流量高峰來(lái)臨時(shí),系統(tǒng)內(nèi)存使用開(kāi)始增多,觸發(fā)了JVM進(jìn)行full GC,進(jìn)而導(dǎo)致大量緩存被釋放(因?yàn)橹髁鱆ava內(nèi)存緩存都采用SoftReference和WeakReference所導(dǎo)致的),而大量請(qǐng)求又使得緩存被迅速填滿(mǎn),這就是反復(fù)緩存。反復(fù)緩存導(dǎo)致了頻繁的full GC,而頻繁full GC往往會(huì)導(dǎo)致系統(tǒng)性能急劇惡化。典型惡化流程圖如下圖:
反復(fù)緩存所導(dǎo)致性能惡化的原因是無(wú)節(jié)制地使用緩存。緩存使用的指導(dǎo)原則是:工程師們?cè)谑褂镁彺鏁r(shí)必須全局考慮,精細(xì)規(guī)劃,確保數(shù)據(jù)完全緩存的情況下,系統(tǒng)仍然不會(huì)頻繁full GC。
為了確保這一點(diǎn),對(duì)于存在多種類(lèi)型緩存以及系統(tǒng)流量變化很大的系統(tǒng),設(shè)計(jì)者必須嚴(yán)格控制緩存大小,甚至廢除緩存(這是典型為了提高流量高峰時(shí)可用性,而降低平均響應(yīng)時(shí)間的一個(gè)例子)。
反復(fù)緩存反模式往往發(fā)生在流量高峰時(shí)候,通過(guò)線(xiàn)性增加機(jī)器和提高機(jī)器內(nèi)存可以大大減少系統(tǒng)崩潰的概率。
 性能優(yōu)化方式
 
 
 
1.水平分割模式
原理和動(dòng)機(jī)
典型的服務(wù)端運(yùn)行流程包含四個(gè)環(huán)節(jié):接收請(qǐng)求、獲取數(shù)據(jù)、處理數(shù)據(jù)、返回結(jié)果。在一次請(qǐng)求中,獲取數(shù)據(jù)和處理數(shù)據(jù)往往多次發(fā)生。在完全串行運(yùn)行的系統(tǒng)里,一次請(qǐng)求總響應(yīng)時(shí)間滿(mǎn)足如下公式:
一次請(qǐng)求總耗時(shí)=解析請(qǐng)求耗時(shí) + ∑(獲取數(shù)據(jù)耗時(shí)+處理數(shù)據(jù)耗時(shí)) + 組裝返回結(jié)果耗時(shí)
大部分耗時(shí)長(zhǎng)的服務(wù)主要時(shí)間都花在中間兩個(gè)環(huán)節(jié),即獲取數(shù)據(jù)和處理數(shù)據(jù)環(huán)節(jié)。
對(duì)于非計(jì)算密集性的系統(tǒng),主要耗時(shí)都用在獲取數(shù)據(jù)上面。獲取數(shù)據(jù)主要有三個(gè)來(lái)源:本地緩存,遠(yuǎn)程緩存或者數(shù)據(jù)庫(kù),遠(yuǎn)程服務(wù)。三者之中,進(jìn)行遠(yuǎn)程數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)或遠(yuǎn)程服務(wù)調(diào)用相對(duì)耗時(shí)較長(zhǎng),特別是對(duì)于需要進(jìn)行多次遠(yuǎn)程調(diào)用的系統(tǒng),串行調(diào)用所帶來(lái)的累加效應(yīng)會(huì)極大地延長(zhǎng)單次請(qǐng)求響應(yīng)時(shí)間,這就增大了系統(tǒng)進(jìn)入長(zhǎng)請(qǐng)求擁塞反模式的概率。
如果能夠?qū)?/span>不同的業(yè)務(wù)請(qǐng)求并行處理,請(qǐng)求總耗時(shí)就會(huì)大大降低。例如下圖中,Client需要對(duì)三個(gè)服務(wù)進(jìn)行調(diào)用,如果采用順序調(diào)用模式,系統(tǒng)的響應(yīng)時(shí)間為18ms,而采用并行調(diào)用只需要7ms。
水平分割模式首先將整個(gè)請(qǐng)求流程切分為必須相互依賴(lài)的多個(gè)Stage,而每個(gè)Stage包含相互獨(dú)立的多種業(yè)務(wù)處理(包括計(jì)算和數(shù)據(jù)獲取)。完成切分之后,水平分割模式串行處理多個(gè)Stage,但是在Stage內(nèi)部并行處理。如此,一次請(qǐng)求總耗時(shí)等于各個(gè)Stage耗時(shí)總和,每個(gè)Stage所耗時(shí)間等于該Stage內(nèi)部最長(zhǎng)的業(yè)務(wù)處理時(shí)間。
水平分割模式有兩個(gè)關(guān)鍵優(yōu)化點(diǎn):減少Stage數(shù)量和降低每個(gè)Stage耗時(shí)。為了減少Stage數(shù)量,需要對(duì)一個(gè)請(qǐng)求中不同業(yè)務(wù)之間的依賴(lài)關(guān)系進(jìn)行深入分析并進(jìn)行解耦,將能夠并行處理的業(yè)務(wù)盡可能地放在同一個(gè)Stage中,最終將流程分解成無(wú)法獨(dú)立運(yùn)行的多個(gè)Stage。降低單個(gè)Stage耗時(shí)一般有兩種思路:1. 在Stage內(nèi)部再?lài)L試水平分割(即遞歸水平分割),2. 對(duì)于一些可以放在任意Stage中進(jìn)行并行處理的流程,將其放在耗時(shí)最長(zhǎng)的Stage內(nèi)部進(jìn)行并行處理,避免耗時(shí)較短的Stage被拉長(zhǎng)。
水平分割模式不僅可以降低系統(tǒng)平均響應(yīng)時(shí)間,而且可以降低TP95響應(yīng)時(shí)間(這兩者有時(shí)候相互矛盾,不可兼得)。通過(guò)降低平均響應(yīng)時(shí)間和TP95響應(yīng)時(shí)間,水平分割模式往往能夠大幅度提高系統(tǒng)吞吐量以及高峰時(shí)期系統(tǒng)可用性,并大大降低系統(tǒng)進(jìn)入長(zhǎng)請(qǐng)求擁塞反模式的概率。
具體案例
例如為用戶(hù)提供高性能的優(yōu)質(zhì)個(gè)性化列表服務(wù),每一次列表服務(wù)請(qǐng)求會(huì)有多個(gè)算法參與,而每個(gè)算法基本上都采用“召回->特征獲取->計(jì)算”的模式。 在進(jìn)行性能優(yōu)化之前,算法之間采用順序執(zhí)行的方式。伴隨著算法工程師的持續(xù)迭代,算法數(shù)量越來(lái)越多,隨之而來(lái)的結(jié)果就是客戶(hù)端響應(yīng)時(shí)間越來(lái)越長(zhǎng),系統(tǒng)很容易進(jìn)入長(zhǎng)請(qǐng)求擁塞反模式。曾經(jīng)有一段時(shí)間,一旦流量高峰來(lái)臨,出現(xiàn)整條服務(wù)鏈路的機(jī)器CPU、內(nèi)存報(bào)警。在對(duì)系統(tǒng)進(jìn)行分析之后,我們采取了如下三個(gè)優(yōu)化措施,最終使得系統(tǒng)TP95時(shí)間降低了一半:
缺點(diǎn)和優(yōu)點(diǎn)
對(duì)成熟系統(tǒng)進(jìn)行水平切割,意味著對(duì)原系統(tǒng)的重大重構(gòu),工程師必須對(duì)業(yè)務(wù)和系統(tǒng)非常熟悉,所以要謹(jǐn)慎使用。水平切割主要有兩方面的難點(diǎn):
雖然進(jìn)行代碼重構(gòu)比較復(fù)雜,但是水平切割模式非常容易理解,只要熟悉系統(tǒng)的業(yè)務(wù),識(shí)別出可以并行處理的流程,就能夠進(jìn)行水平切割。有時(shí)候,即使少量的并行化也可以顯著提高整體性能。
對(duì)于新系統(tǒng)而言,如果存在可預(yù)見(jiàn)的性能問(wèn)題,把水平分割模式作為一個(gè)重要的設(shè)計(jì)理念將會(huì)大大地提高系統(tǒng)的可用性、降低系統(tǒng)的重構(gòu)風(fēng)險(xiǎn)。總的來(lái)說(shuō),雖然存在一些具體實(shí)施的難點(diǎn),水平分割模式是一個(gè)非常有效、容易識(shí)別和理解的模式。
2.垂直分割模式
原理和動(dòng)機(jī)
對(duì)于移動(dòng)互聯(lián)網(wǎng)節(jié)奏的公司,新需求往往是一波接一波。基于代碼復(fù)用原則,工程師們往往會(huì)在一個(gè)系統(tǒng)實(shí)現(xiàn)大量相似卻完全不相干的功能。伴隨著功能的增強(qiáng),系統(tǒng)實(shí)際上變得越來(lái)越脆弱。這種脆弱可能表現(xiàn)在系統(tǒng)響應(yīng)時(shí)間變長(zhǎng)、吞吐量降低或者可用性降低。導(dǎo)致系統(tǒng)脆弱原因主要來(lái)自?xún)煞矫娴臎_突:資源使用沖突和可用性不一致沖突。
資源使用沖突是導(dǎo)致系統(tǒng)脆弱的一個(gè)重要原因。不同業(yè)務(wù)功能并存于同一個(gè)運(yùn)行系統(tǒng)里面意味著資源共享,同時(shí)也意味著資源使用沖突。可能產(chǎn)生沖突的資源包括:CPU、內(nèi)存、網(wǎng)絡(luò)、I/O等。
例如:一種業(yè)務(wù)功能,無(wú)論其調(diào)用量多么小,都有一些內(nèi)存開(kāi)銷(xiāo)。對(duì)于存在大量緩存的業(yè)務(wù)功能,業(yè)務(wù)功能數(shù)量的增加會(huì)極大地提高內(nèi)存消耗,從而增大系統(tǒng)進(jìn)入反復(fù)緩存反模式的概率。對(duì)于CPU密集型業(yè)務(wù),當(dāng)產(chǎn)生沖突的時(shí)候,響應(yīng)時(shí)間會(huì)變慢,從而增大了系統(tǒng)進(jìn)入長(zhǎng)請(qǐng)求擁塞反模式的可能性。
不加區(qū)別地將不同可用性要求的業(yè)務(wù)功能放入一個(gè)系統(tǒng)里,會(huì)導(dǎo)致系統(tǒng)整體可用性變低。當(dāng)不同業(yè)務(wù)功能糅合在同一運(yùn)行系統(tǒng)里面的時(shí)候,在運(yùn)維和機(jī)器層面對(duì)不同業(yè)務(wù)的可用性、可靠性進(jìn)行調(diào)配將會(huì)變得很困難。但是,在高峰流量導(dǎo)致系統(tǒng)瀕臨崩潰的時(shí)候,最有效的解決手段往往是運(yùn)維,而最有效手段的失效也就意味著核心業(yè)務(wù)的可用性降低。
垂直分割思路就是將系統(tǒng)按照不同的業(yè)務(wù)功能進(jìn)行分割,主要有兩種分割模式:
1.部署垂直分割
部署垂直分割主要是按照可用性要求將系統(tǒng)進(jìn)行等價(jià)分類(lèi),不同可用性業(yè)務(wù)部署在不同機(jī)器上,高可用業(yè)務(wù)單獨(dú)部署;
2.代碼垂直分割。
代碼垂直分割就是讓不同業(yè)務(wù)系統(tǒng)不共享代碼,徹底解決系統(tǒng)資源使用沖突問(wèn)題。
缺點(diǎn)和優(yōu)點(diǎn)
垂直分割主要的缺點(diǎn)主要有兩個(gè):
垂直分割是一個(gè)非常簡(jiǎn)單而又有效的性能優(yōu)化模式,特別適用于系統(tǒng)已經(jīng)出現(xiàn)問(wèn)題而又需要快速解決的場(chǎng)景。部署層次的分割既安全又有效。需要說(shuō)明的是部署分割和簡(jiǎn)單意義上的加機(jī)器不是一回事,在大部分情況下,即使不增加機(jī)器,僅通過(guò)部署分割,系統(tǒng)整體吞吐量和可用性都有可能提升。所以就短期而言,這幾乎是一個(gè)零成本方案。對(duì)于代碼層次的分割,開(kāi)發(fā)工程師需要在業(yè)務(wù)承接效率和系統(tǒng)可用性上面做一些折衷考慮。
3.降級(jí)模式
原理和動(dòng)機(jī)
降級(jí)模式是系統(tǒng)性能保障的最后一道防線(xiàn)。理論上講,不存在絕對(duì)沒(méi)有漏洞的系統(tǒng),或者說(shuō),最好的安全措施就是為處于崩潰狀態(tài)的系統(tǒng)提供預(yù)案。從系統(tǒng)性能優(yōu)化的角度來(lái)講,不管系統(tǒng)設(shè)計(jì)地多么完善,總會(huì)有一些意料之外的情況會(huì)導(dǎo)致系統(tǒng)性能惡化,最終可能導(dǎo)致崩潰,所以對(duì)于要求高可用性的服務(wù),在系統(tǒng)設(shè)計(jì)之初,就必須做好降級(jí)設(shè)計(jì)。根據(jù)作者的經(jīng)驗(yàn),良好的降級(jí)方案應(yīng)該包含如下措施:
典型的降級(jí)策略有三種:流量降級(jí)、效果降級(jí)和功能性降級(jí)。
流量降級(jí)是指當(dāng)通過(guò)主動(dòng)拒絕處理部分流量的方式讓系統(tǒng)正常服務(wù)未降級(jí)的流量,這會(huì)造成部分用戶(hù)服務(wù)不可用;效果降級(jí)表現(xiàn)為服務(wù)質(zhì)量的降級(jí),即在流量高峰時(shí)期用相對(duì)低質(zhì)量、低延時(shí)的服務(wù)來(lái)替換高質(zhì)量、高延時(shí)的服務(wù),保障所有用戶(hù)的服務(wù)可用性;功能性降級(jí)也表現(xiàn)為服務(wù)質(zhì)量的降級(jí),指的是通過(guò)減少功能的方式來(lái)提高用戶(hù)的服務(wù)可用性。效果降級(jí)和功能性降級(jí)比較接近,效果降級(jí)強(qiáng)調(diào)的是主功能服務(wù)質(zhì)量的下降,功能性降級(jí)更多強(qiáng)調(diào)的是輔助性功能的缺失。
缺點(diǎn)和優(yōu)點(diǎn)
為了使系統(tǒng)具備降級(jí)功能,需要撰寫(xiě)大量的代碼,而降級(jí)代碼往往比正常業(yè)務(wù)代碼更難寫(xiě),更容易出錯(cuò)。在確定使用降級(jí)模式的前提下,工程師需要權(quán)衡這三種降級(jí)策略的利弊。大多數(shù)面向C端的系統(tǒng)傾向于采用效果降級(jí)和功能性降級(jí)策略,但是有些功能性模塊(比如下單功能)是不能進(jìn)行效果和功能性降級(jí)的,只能采用流量降級(jí)策略。對(duì)于不能接受降級(jí)后果的系統(tǒng),必須要通過(guò)其他方式來(lái)提高系統(tǒng)的可用性。
總的來(lái)說(shuō),降級(jí)模式是一種設(shè)計(jì)安全準(zhǔn)則,任何高可用性要求的服務(wù),必須要按照降級(jí)模式的準(zhǔn)則去設(shè)計(jì)。對(duì)于違背這條設(shè)計(jì)原則的系統(tǒng),或早或晚,系統(tǒng)總會(huì)因?yàn)槟承﹩?wèn)題導(dǎo)致崩潰而降低可用性。不過(guò),降級(jí)模式并非不需要成本,也不符合最小可用原則,所以對(duì)于處于MVP階段的系統(tǒng),或者對(duì)于可用性要求不高的系統(tǒng),降級(jí)模式并非必須采納的原則。
4.其他性能優(yōu)化建議
對(duì)于無(wú)法采用系統(tǒng)性的模式方式講解的性能優(yōu)化手段,給出一些總結(jié)性的建議:
你可能也喜歡:
總結(jié)
以上是生活随笔為你收集整理的阿里P8架构师谈:流量高峰时期的性能瓶颈有哪些、以及如何来解决的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: 美团AI全景图:吃喝玩乐背后的黑科技
- 下一篇: 自然场景人脸检测技术实践
