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