某月黑風(fēng)高之夜,某打車(chē)平臺(tái)上線了一大波(G+)優(yōu)惠活動(dòng),眾人紛紛下單。于是乎,該打車(chē)平臺(tái)使用的智能提示服務(wù)扛不住直接趴窩了(如下圖)。事后,負(fù)責(zé)智能提示服務(wù)開(kāi)發(fā)和運(yùn)維的有關(guān)部門(mén)開(kāi)會(huì)后決定:必須對(duì)智能提示服務(wù)進(jìn)行一次全面深入的性能摸底,立刻!現(xiàn)在!馬上!
那么一大坨問(wèn)題就迎面而來(lái):對(duì)于智能提示這樣的后臺(tái)服務(wù),性能測(cè)試過(guò)程中應(yīng)該關(guān)心那些指標(biāo)?這些指標(biāo)代表什么含義?這些指標(biāo)的通過(guò)標(biāo)準(zhǔn)是什么?下面將為您一一解答。
概述
不同人群關(guān)注的性能指標(biāo)各有側(cè)重。后臺(tái)服務(wù)接口的調(diào)用者一般只關(guān)心吞吐量、響應(yīng)時(shí)間等外部指標(biāo)。后臺(tái)服務(wù)的所有者不僅僅關(guān)注外部指標(biāo),還會(huì)關(guān)注CPU、內(nèi)存、負(fù)載等內(nèi)部指標(biāo)。
拿某打車(chē)平臺(tái)來(lái)說(shuō),它所關(guān)心的是智能提示的外部指標(biāo)能不能抗住因大波優(yōu)惠所導(dǎo)致的流量激增。而對(duì)于智能提示服務(wù)的開(kāi)發(fā)、運(yùn)維、測(cè)試人員,不僅僅關(guān)注外部指標(biāo),還會(huì)關(guān)注CPU、內(nèi)存、IO等內(nèi)部指標(biāo),以及部署方式、服務(wù)器軟硬件配置等運(yùn)維相關(guān)事項(xiàng)。
外部指標(biāo)
從外部看,性能測(cè)試主要關(guān)注如下三個(gè)指標(biāo)
- 吞吐量:每秒鐘系統(tǒng)能夠處理的請(qǐng)求數(shù)、任務(wù)數(shù)。
- 響應(yīng)時(shí)間:服務(wù)處理一個(gè)請(qǐng)求或一個(gè)任務(wù)的耗時(shí)。
-
錯(cuò)誤率:一批請(qǐng)求中結(jié)果出錯(cuò)的請(qǐng)求所占比例。
響應(yīng)時(shí)間的指標(biāo)取決于具體的服務(wù)。如智能提示一類(lèi)的服務(wù),返回的數(shù)據(jù)有效周期短(用戶多輸入一個(gè)字母就需要重新請(qǐng)求),對(duì)實(shí)時(shí)性要求比較高,響應(yīng)時(shí)間的上限一般在100ms以內(nèi)。而導(dǎo)航一類(lèi)的服務(wù),由于返回結(jié)果的使用周期比較長(zhǎng)(整個(gè)導(dǎo)航過(guò)程中),響應(yīng)時(shí)間的上限一般在2-5s。
對(duì)于響應(yīng)時(shí)間的統(tǒng)計(jì),應(yīng)從均值、.90、.99、分布等多個(gè)角度統(tǒng)計(jì),而不僅僅是給出均值。下圖是響應(yīng)時(shí)間統(tǒng)計(jì)的一個(gè)例子
吞吐量的指標(biāo)受到響應(yīng)時(shí)間、服務(wù)器軟硬件配置、網(wǎng)絡(luò)狀態(tài)等多方面因素影響。
- 吞吐量越大,響應(yīng)時(shí)間越長(zhǎng)。
- 服務(wù)器硬件配置越高,吞吐量越大。
- 網(wǎng)絡(luò)越差,吞吐量越小。
在低吞吐量下的響應(yīng)時(shí)間的均值、分布比較穩(wěn)定,不會(huì)產(chǎn)生太大的波動(dòng)。
在高吞吐量下,響應(yīng)時(shí)間會(huì)隨著吞吐量的增長(zhǎng)而增長(zhǎng),增長(zhǎng)的趨勢(shì)可能是線性的,也可能接近指數(shù)的。當(dāng)吞吐量接近系統(tǒng)的峰值時(shí),響應(yīng)時(shí)間會(huì)出現(xiàn)激增。
錯(cuò)誤率和服務(wù)的具體實(shí)現(xiàn)有關(guān)。通常情況下,由于網(wǎng)絡(luò)超時(shí)等外部原因造成的錯(cuò)誤比例不應(yīng)超過(guò)5%%,由于服務(wù)本身導(dǎo)致的錯(cuò)誤率不應(yīng)超過(guò)1% 。
內(nèi)部指標(biāo)
從服務(wù)器的角度看,性能測(cè)試主要關(guān)注CPU、內(nèi)存、服務(wù)器負(fù)載、網(wǎng)絡(luò)、磁盤(pán)IO等
CPU
后臺(tái)服務(wù)的所有指令和數(shù)據(jù)處理都是由CPU負(fù)責(zé),服務(wù)對(duì)CPU的利用率對(duì)服務(wù)的性能起著決定性的作用。
Linux系統(tǒng)的CPU主要有如下幾個(gè)維度的統(tǒng)計(jì)數(shù)據(jù)
- us:用戶態(tài)使用的cpu時(shí)間百分比
- sy:系統(tǒng)態(tài)使用的cpu時(shí)間百分比
- ni:用做nice加權(quán)的進(jìn)程分配的用戶態(tài)cpu時(shí)間百分比
- id:空閑的cpu時(shí)間百分比
- wa:cpu等待IO完成時(shí)間百分比
- hi:硬中斷消耗時(shí)間百分比
-
si:軟中斷消耗時(shí)間百分比
下圖是線上開(kāi)放平臺(tái)轉(zhuǎn)發(fā)服務(wù)某臺(tái)服務(wù)器上top命令的輸出,下面以這個(gè)服務(wù)為例對(duì)CPU各項(xiàng)指標(biāo)進(jìn)行說(shuō)明
us & sy:大部分后臺(tái)服務(wù)使用的CPU時(shí)間片中us和sy的占用比例是最高的。同時(shí)這兩個(gè)指標(biāo)又是互相影響的,us的比例高了,sy的比例就低,反之亦然。通常sy比例過(guò)高意味著被測(cè)服務(wù)在用戶態(tài)和系統(tǒng)態(tài)之間切換比較頻繁,此時(shí)系統(tǒng)整體性能會(huì)有一定下降。另外,在使用多核CPU的服務(wù)器上,CPU 0負(fù)責(zé)CPU各核間的調(diào)度,CPU 0上的使用率過(guò)高會(huì)導(dǎo)致其他CPU核心之間的調(diào)度效率變低。因此測(cè)試過(guò)程中CPU 0需要重點(diǎn)關(guān)注。
ni:每個(gè)Linux進(jìn)程都有個(gè)優(yōu)先級(jí),優(yōu)先級(jí)高的進(jìn)程有優(yōu)先執(zhí)行的權(quán)利,這個(gè)叫做pri。進(jìn)程除了優(yōu)先級(jí)外,還有個(gè)優(yōu)先級(jí)的修正值。這個(gè)修正值就叫做進(jìn)程的nice值。一般來(lái)說(shuō),被測(cè)服務(wù)和服務(wù)器整體的ni值不會(huì)很高。如果測(cè)試過(guò)程中ni的值比較高,需要從服務(wù)器Linux系統(tǒng)配置、被測(cè)服務(wù)運(yùn)行參數(shù)查找原因
id:線上服務(wù)運(yùn)行過(guò)程中,需要保留一定的id冗余來(lái)應(yīng)對(duì)突發(fā)的流量激增。在性能測(cè)試過(guò)程中,如果id一直很低,吞吐量上不去,需要檢查被測(cè)服務(wù)線程/進(jìn)程配置、服務(wù)器系統(tǒng)配置等。
wa:磁盤(pán)、網(wǎng)絡(luò)等IO操作會(huì)導(dǎo)致CPU的wa指標(biāo)提高。通常情況下,網(wǎng)絡(luò)IO占用的wa資源不會(huì)很高,而頻繁的磁盤(pán)讀寫(xiě)會(huì)導(dǎo)致wa激增。如果被測(cè)服務(wù)不是IO密集型的服務(wù),那需要檢查被測(cè)服務(wù)的日志量、數(shù)據(jù)載入頻率等。
hi & si:硬中斷是外設(shè)對(duì)CPU的中斷,即外圍硬件發(fā)給CPU或者內(nèi)存的異步信號(hào)就是硬中斷信號(hào);軟中斷由軟件本身發(fā)給操作系統(tǒng)內(nèi)核的中斷信號(hào)。通常是由硬中斷處理程序或進(jìn)程調(diào)度程序?qū)Σ僮飨到y(tǒng)內(nèi)核的中斷,也就是我們常說(shuō)的系統(tǒng)調(diào)用(System Call)。在性能測(cè)試過(guò)程中,hi會(huì)有一定的CPU占用率,但不會(huì)太高。對(duì)于IO密集型的服務(wù),si的CPU占用率會(huì)高一些。
內(nèi)存
性能測(cè)試過(guò)程中對(duì)內(nèi)存監(jiān)控的主要目的是檢查被測(cè)服務(wù)所占用內(nèi)存的波動(dòng)情況。
在Linux系統(tǒng)中有多個(gè)命令可以獲取指定進(jìn)程的內(nèi)存使用情況,最常用的是top命令,如下圖所示
其中
- VIRT:進(jìn)程所使用的虛擬內(nèi)存的總數(shù)。它包括所有的代碼,數(shù)據(jù)和共享庫(kù),加上已換出的頁(yè)面,所有已申請(qǐng)的總內(nèi)存空間
- RES:進(jìn)程正在使用的沒(méi)有交換的物理內(nèi)存(棧、堆),申請(qǐng)內(nèi)存后該內(nèi)存段已被重新賦值
- SHR:進(jìn)程使用共享內(nèi)存的總數(shù)。該數(shù)值只是反映可能與其它進(jìn)程共享的內(nèi)存,不代表這段內(nèi)存當(dāng)前正被其他進(jìn)程使用
- SWAP:進(jìn)程使用的虛擬內(nèi)存中被換出的大小,交換的是已經(jīng)申請(qǐng),但沒(méi)有使用的空間,包括(棧、堆、共享內(nèi)存)
- DATA:進(jìn)程除可執(zhí)行代碼以外的物理內(nèi)存總量,即進(jìn)程棧、堆申請(qǐng)的總空間
從上面的解釋可以看出,測(cè)試過(guò)程中主要監(jiān)控RES和VIRT,對(duì)于使用了共享內(nèi)存的多進(jìn)程架構(gòu)服務(wù),還需要監(jiān)沙發(fā)控SHR。
LOAD(服務(wù)器負(fù)載)
Linux的系統(tǒng)負(fù)載指運(yùn)行隊(duì)列的平均長(zhǎng)度,也就是等待CPU的平均進(jìn)程數(shù)
從服務(wù)器負(fù)載的定義可以看出,服務(wù)器運(yùn)行最理想的狀態(tài)是所有CPU核心的運(yùn)行隊(duì)列都為1,即所有活動(dòng)進(jìn)程都在運(yùn)行,沒(méi)有等待。這種狀態(tài)下服務(wù)器運(yùn)行在負(fù)載閾值下。
通常情況下,按照經(jīng)驗(yàn)值,服務(wù)器的負(fù)載應(yīng)位于閾值的70%~80%,這樣既能利用服務(wù)器大部分性能,又留有一定的性能冗余應(yīng)對(duì)流量增長(zhǎng)。
Linux提供了很多查看系統(tǒng)負(fù)載的命令,最常用的是top和uptime
top和uptime針對(duì)負(fù)載的輸出內(nèi)容相同,都是系統(tǒng)最近1分鐘、5分鐘、15分鐘的負(fù)載均值
查看系統(tǒng)負(fù)載閾值的命令如下
在性能測(cè)試過(guò)程中,系統(tǒng)負(fù)載是評(píng)價(jià)整個(gè)系統(tǒng)運(yùn)行狀況最重要的指標(biāo)之一。通常情況下,壓力測(cè)試時(shí)系統(tǒng)負(fù)載應(yīng)接近但不能超過(guò)閾值,并發(fā)測(cè)試時(shí)的系統(tǒng)負(fù)載最高不能超過(guò)閾值的80%,穩(wěn)定性測(cè)試時(shí),系統(tǒng)負(fù)載應(yīng)在閾值的50%左右。
網(wǎng)絡(luò)
性能測(cè)試中網(wǎng)絡(luò)監(jiān)控主要包括網(wǎng)絡(luò)流量、網(wǎng)絡(luò)連接狀態(tài)的監(jiān)控。
-
網(wǎng)絡(luò)流量監(jiān)控
可以使用nethogs命令。該命令與top類(lèi)似,是一個(gè)實(shí)時(shí)交互的命令,運(yùn)行界面如下
在后臺(tái)服務(wù)性能測(cè)試中,對(duì)于返回文本結(jié)果的服務(wù),并不需要太多關(guān)注在流量方面。
-
網(wǎng)絡(luò)連接狀態(tài)監(jiān)控
性能測(cè)試中對(duì)網(wǎng)絡(luò)的監(jiān)控主要是監(jiān)控網(wǎng)絡(luò)連接狀態(tài)的變化和異常。對(duì)于使用TCP協(xié)議的服務(wù),需要監(jiān)控服務(wù)已建立連接的變化情況(即ESTABLISHED狀態(tài)的TCP連接)。對(duì)于HTTP協(xié)議的服務(wù),需要監(jiān)控被測(cè)服務(wù)對(duì)應(yīng)進(jìn)程的網(wǎng)絡(luò)緩沖區(qū)的狀態(tài)、TIME_WAIT狀態(tài)的連接數(shù)等。Linux自帶的很多命令如netstat、ss都支持如上功能。下圖是netstat對(duì)指定pid進(jìn)程的監(jiān)控結(jié)果
磁盤(pán)IO
性能測(cè)試過(guò)程中,如果被測(cè)服務(wù)對(duì)磁盤(pán)讀寫(xiě)過(guò)于頻繁,會(huì)導(dǎo)致大量請(qǐng)求處于IO等待的狀態(tài),系統(tǒng)負(fù)載升高,響應(yīng)時(shí)間變長(zhǎng),吞吐量下降。
Linux下可以用iostat命令來(lái)監(jiān)控磁盤(pán)狀態(tài),如下圖
- tps:該設(shè)備每秒的傳輸次數(shù)。“一次傳輸”意思是“一次I/O請(qǐng)求”。多個(gè)邏輯請(qǐng)求可能會(huì)被合并為“一次I/O請(qǐng)求”。“一次傳輸”請(qǐng)求的大小是未知的
- kB_read/s:每秒從設(shè)備(driveexpressed)讀取的數(shù)據(jù)量,單位為Kilobytes
- kB_wrtn/s:每秒向設(shè)備(driveexpressed)寫(xiě)入的數(shù)據(jù)量,單位為Kilobytes
- kB_read:讀取的總數(shù)據(jù)量,單位為Kilobytes
- kB_wrtn:寫(xiě)入的總數(shù)量數(shù)據(jù)量,單位為Kilobytes
從iostat的輸出中,能夠獲得系統(tǒng)運(yùn)行最基本的統(tǒng)計(jì)數(shù)據(jù)。但對(duì)于性能測(cè)試來(lái)說(shuō),這些數(shù)據(jù)不能提供更多的信息。需要加上-x參數(shù)
- rrqm/s:每秒這個(gè)設(shè)備相關(guān)的讀取請(qǐng)求有多少被Merge了(當(dāng)系統(tǒng)調(diào)用需要讀取數(shù)據(jù)的時(shí)候,VFS將請(qǐng)求發(fā)到各個(gè)FS,如果FS發(fā)現(xiàn)不同的讀取請(qǐng)求讀取的是相同Block的數(shù)據(jù),F(xiàn)S會(huì)將這個(gè)請(qǐng)求合并Merge)
- wrqm/s:每秒這個(gè)設(shè)備相關(guān)的寫(xiě)入請(qǐng)求有多少被Merge了
- await:每一個(gè)IO請(qǐng)求的處理的平均時(shí)間(單位是毫秒)
- %util:在統(tǒng)計(jì)時(shí)間內(nèi)所有處理IO時(shí)間,除以總共統(tǒng)計(jì)時(shí)間。例如,如果統(tǒng)計(jì)間隔1秒,該設(shè)備有0.8秒在處理IO,而0.2秒閑置,那么該設(shè)備的%util = 0.8/1 = 80%,該參數(shù)暗示了設(shè)備的繁忙程度。
常見(jiàn)性能瓶頸
- 吞吐量到上限時(shí)系統(tǒng)負(fù)載未到閾值:一般是被測(cè)服務(wù)分配的系統(tǒng)資源過(guò)少導(dǎo)致的。測(cè)試過(guò)程中如果發(fā)現(xiàn)此類(lèi)情況,可以從ulimit、系統(tǒng)開(kāi)啟的線程數(shù)、分配的內(nèi)存等維度定位問(wèn)題原因
- CPU的us****和sy****不高,但wa很高:如果被測(cè)服務(wù)是磁盤(pán)IO密集型型服務(wù),wa高屬于正常現(xiàn)象。但如果不是此類(lèi)服務(wù),最可能導(dǎo)致wa高的原因有兩個(gè),一是服務(wù)對(duì)磁盤(pán)讀寫(xiě)的業(yè)務(wù)邏輯有問(wèn)題,讀寫(xiě)頻率過(guò)高,寫(xiě)入數(shù)據(jù)量過(guò)大,如不合理的數(shù)據(jù)載入策略、log過(guò)多等,都有可能導(dǎo)致這種問(wèn)題。二是服務(wù)器內(nèi)存不足,服務(wù)在swap分區(qū)不停的換入換出。
- 同一請(qǐng)求的響應(yīng)時(shí)間忽大忽小:在正常吞吐量下發(fā)生此問(wèn)題,可能的原因有兩方面,一是服務(wù)對(duì)資源的加鎖邏輯有問(wèn)題,導(dǎo)致處理某些請(qǐng)求過(guò)程中花了大量的時(shí)間等待資源解鎖;二是Linux本身分配給服務(wù)的資源有限,某些請(qǐng)求需要等待其他請(qǐng)求釋放資源后才能繼續(xù)執(zhí)行。
- 內(nèi)存持續(xù)上漲:在吞吐量固定的前提下,如果內(nèi)存持續(xù)上漲,那么很有可能是被測(cè)服務(wù)存在明顯的內(nèi)存泄漏,需要使用valgrind等內(nèi)存檢查工具進(jìn)行定位。
舉個(gè) (栗子) 例子
智能提示服務(wù)趴窩了以后,必須立刻對(duì)其做性能摸底。根據(jù)目前的情況,測(cè)試結(jié)果中需要提供外部指標(biāo)和內(nèi)部指標(biāo)。
智能提示服務(wù)的架構(gòu)和每個(gè)模塊的功能如下圖所示
從圖中我們可以看出,測(cè)試前智能提示服務(wù)的底層數(shù)據(jù)服務(wù)已經(jīng)確定了性能上限。因此,本次測(cè)試我們的任務(wù)是在底層數(shù)據(jù)服務(wù)性能為3500qps的前提下,找到智能提示服務(wù)上游各個(gè)模塊的性能上限。
一個(gè)完整的后臺(tái)服務(wù)性能測(cè)試流程如下圖所示。
測(cè)試前準(zhǔn)備:
- 測(cè)試數(shù)據(jù):由于智能提示已經(jīng)在線上運(yùn)行,本次測(cè)試使用智能提示趴窩那天的日志作為測(cè)試數(shù)據(jù)
- QPS預(yù)估:本次測(cè)試就是為了找這個(gè)數(shù)
- 服務(wù)器配置:使用與線上軟硬件配置相同的服務(wù)器
壓測(cè)過(guò)程:
我們使用Jmeter發(fā)送測(cè)試數(shù)據(jù)來(lái)模擬用戶請(qǐng)求,Jmeter測(cè)試配置文件使用的原件如下圖所示。從圖中可以看出,性能測(cè)試的配置文件主要由數(shù)據(jù)文件配置(線程間共享方式、到達(dá)末尾時(shí)的行為等)、吞吐量控制、HTTP采樣器(域名、端口、HTTP METHOD、請(qǐng)求body等)、響應(yīng)斷言(對(duì)返回結(jié)果的內(nèi)容進(jìn)行校驗(yàn))。
- 數(shù)據(jù)文件配置
- 吞吐量控制
- HTTP請(qǐng)求采樣
- 響應(yīng)斷言
- CPU
在linux中,sar、top、ps等命令都可以對(duì)cpu使用情況進(jìn)行監(jiān)控。一般來(lái)說(shuō),最常用的是top命令。top命令的輸出如下:
top命令是一個(gè)交互式命令,運(yùn)行后會(huì)一直保持在終端并定時(shí)刷新。在性能測(cè)試中,可以使用如下參數(shù)讓top命令只運(yùn)行一次
$top –n 1 –b –p ${pid}
- 服務(wù)器負(fù)載
linux中,服務(wù)器負(fù)載使用uptime命令獲取,該命令的輸出如下圖
每一列的含義如下:
“當(dāng)前時(shí)間 系統(tǒng)運(yùn)行時(shí)長(zhǎng) 登錄的用戶數(shù)最 近1分鐘、5分鐘、15分鐘的平均負(fù)載”
-
內(nèi)存
在linux中, top、ps命令都可以對(duì)指定進(jìn)程的內(nèi)存使用狀況進(jìn)行查看。但最準(zhǔn)確的信息在/proc/${PID}/status中,如下圖
上面命令的輸出中,我們重點(diǎn)關(guān)注VmRSS、VmData、VmSize
-
磁盤(pán)IO
磁盤(pán)監(jiān)控?cái)?shù)據(jù)使用iostat命令獲取
測(cè)試報(bào)告輸出
在統(tǒng)計(jì)完性能測(cè)試過(guò)程中收集的監(jiān)控指標(biāo)后,就可以輸出性能報(bào)告了。
通常來(lái)說(shuō),性能報(bào)告中要包含如下內(nèi)容:測(cè)試結(jié)論:包括被測(cè)服務(wù)最大QPS、響應(yīng)時(shí)間等指標(biāo)是否達(dá)到期望,部署建議等。
測(cè)試環(huán)境描述:包括性能需求、測(cè)試用服務(wù)器配置、測(cè)試數(shù)據(jù)來(lái)源、測(cè)試方法等
監(jiān)控指標(biāo)統(tǒng)計(jì):響應(yīng)時(shí)間統(tǒng)計(jì)、QPS、服務(wù)器指標(biāo)統(tǒng)計(jì)、進(jìn)程指標(biāo)統(tǒng)計(jì)。建議最好用圖表來(lái)表示統(tǒng)計(jì)數(shù)據(jù)。
結(jié)語(yǔ)
測(cè)試完畢后,得出的結(jié)論是單臺(tái)智能提示服務(wù)的性能是300qps,線上整套智能提示服務(wù)的性能是1800qps;而月黑風(fēng)高那天的流量大概是5000qps+,難怪智能提示趴窩,確實(shí)流量太大,遠(yuǎn)超線上的吞吐容量。
最后,智能提示服務(wù)申請(qǐng)了服務(wù)器進(jìn)行擴(kuò)容,并對(duì)某打車(chē)平臺(tái)的流量進(jìn)行了限制,既開(kāi)源又節(jié)流,保證今后月黑風(fēng)高之夜一眾約酒、約飯、約P之人的打車(chē)體驗(yàn),提高了各種約的成功率,可謂功德無(wú)量。
轉(zhuǎn):騰訊移動(dòng)品質(zhì)中心TMQ