1.性能評估模型概述
我們的系統性能到底能不能夠支撐線上真實大量的訂單交易?
我想,這是我們每一個互聯網交易或者負責大並發項目的同學都很關心的問題,也是性能評估模型篇需要解答的最終問題。所以我們就帶着這個問題來一步步深入性能測試。本問題的難度不在於一個簡單的結果,而在於答案背后的一系列性能測試的評估數據和算法,以及如何建立一個良好可持續的“性能評估模型”。
通常來講,性能測試是指通過自動化的測試工具模擬多種正常、峰值以及異常負載條件來對系統的各項性能指標進行測試。
而要回答“能否支撐線上真實大量的訂單交易”這樣帶有預測性的問題,實際上還需要用上另一種手段,即“性能預測”,而“在線性能評估模型”就是用來做性能預測的。
在預測之前,我們先來做一個數據分析,通過這個分析我們可以大概了解線上與線下的推算過程。
2013年11月11日,支付寶實現了當天交易總金額350億元,訂單總數1.8億筆(其中手機支付占24%),活躍用戶1.2億。(來源:支付寶官方微博http://weibo.com/1627897870/AiiAjEwHO)
顯然這是一個非常震驚的數字,它見證着電商的今天也預示着電商的未來。針對這個數字,下面我們就一起來剖析數字背后的性能情況。
雙11當天,支付寶的訂單數是1.8億筆,意味着每小時訂單數達到1.8億 / 24 = 750萬筆,也意味着每秒訂單數達到750萬 / 3600 = 2083筆。
首先,讓我們先來看看吞吐率指標(TPS),假設支付寶有100台前置服務器,分到每台機器就是每秒處理訂單2083筆/100 = 20筆。這是不是意味着只要單台服務器的性能達到20tps,我們的線上服務就足以支撐每天1.8億的交易量呢?答案顯然不是。
我們先來看看淘寶網每天交易量分布圖:
可以看到,交易量並不是24小時平均分布的,從早上8點開始到晚上12點才是交易量發生的主要時間段,也就是說實際上每天只有2/3的時間(16小時)才是有效時間。我們的性能指標應該調整到20tps * 150% =30tps。
即使是16個小時中,交易量也不是平均的,在午飯和晚飯時間會出現兩個波谷,晚上8點到11點之間是一天的最高峰。最高峰大約是平均值的1.2倍,如果我們不想損失掉高峰時期的交易量的話,我們的吞吐率指標需要再上調到30tps * 1.2 = 36tps。
以上只是一個普通日子的交易量分布情況,如果有某些重大活動事件,比如限時搶購、定時秒殺等活動,那么我們很可能在短時間承受幾倍甚至十幾倍的壓力。如下圖是公司某年某活動當天的交易量分布圖:
總體交易量是平日的幾倍到十幾倍,交易量從零點開始就達到一個小高峰,凌晨2點后逐漸降到冰點,早上8點又開始了一天的持續熱度,下午7點出現一個小波谷緊接着就迎來了晚上11點左右的最高峰。對於這種特別龐大的活動我們需要提前做好性能預案,以往的數據就是我們最好的參考。
通常來講,我們對於系統的性能要求在每天高峰時期的1.5倍到4倍,如果按2倍計算,那么我們的吞吐率指標就繼續上調到 36tps * 2 = 72tps。
好了,單台服務器的性能達標了72tps。但是100台服務器加起來就能承載 72tps * 100 =7200tps嗎?
比較難,這依賴於我們的負載均衡算法。假設我們有一個還不錯的算法,但也不能保證長時間絕對的公平,所以單台服務器還需要做好壓力波動的緩沖,如果按1.5倍計算,這樣我們的指標又要上調到72tps*150% = 98tps。
這里,我們已經把對單台服務器的性能指標從20tps逐漸上調到近100tps,是原來的5倍。當然這里還遠沒有結束。這1.8億筆只是單一的下單操作的PV,假設用戶每下單一筆,需要伴隨着10次查詢,3次提交,那么我們的服務器需要再評估其他或查詢或提交的性能。假設這些其他附帶請求的壓力總和可能還得增大5倍,即達到98tps * 5 = 500tps。
還沒完,這只是100台前置服務器,后面還有我們的核心業務層、消息系統、數據庫系統、第三方依賴等等。它們中的任何一方都有可能成為性能瓶頸,雖然我們的分析假設了對外依賴都不是瓶頸的情況,但實際上往往就是某些不起眼的有限資源的依賴導致了整體吞吐率的下降。
這是一個水桶效應,裝水量是由最小的那塊板決定的。顯然我們有必要對每一個子系統(公司內和公司外)分別做單獨的性能測試和評估。
完了嗎?可能還沒有。假設我們的穩定性足夠好,好到99.99%,即使這樣,在面對超大量訂單(1.8億)的時候也還是意味着有1.8萬個訂單是失敗的。
每一次失敗對用戶來講都是一次糟糕的體驗,可能還會因此引起一些連鎖反應。所以穩定性也是系統性能的重要指標,我們做性能測試不能僅僅關注數量,還要關注質量。
對了,既然我們已經提到用戶體驗,那就不得不談響應時間(RT)了,這是性能指標的又一個維度。
一般用戶不會關心你有多少台服務器,也不會關心服務器能支撐多大的交易量,他們只關心你讓他等了多長的時間。關於這方面的研究有不少,較新的觀點可能是:
用戶的耐心似乎一直在下降。不管怎么樣,從性能角度上看,用戶的訴求就是一句話:“不要讓我等!”。為了不讓用戶等,我們的性能測試需要針對不同場景給出不同的考察指標,比如前端頁面加載時間,后端系統響應時間,並統計出最大、最小、平均值、標准差等等。
好吧,到這里我們已經層層分析,從TPS開始到用戶體驗上。需要注意的是,在分析中我們使用了一些模糊的參數,比如前面說1.5倍到4倍,那到底應該是多少呢?
我想不同的業務、不同的架構、甚至不同的工程師,都有可能導致不同的結果。
而對於性能預測來講,最重要的是建立起一個系統良好的可持續的“在線性能評估模型”,將線上和線下性能跟蹤形成閉環,並不斷調整動態發展,那樣我們就可以適應任何的差異化,就算某一次我們評估錯了,我們可以及時調整糾正,下一次我們就能更准了。
1.1 閉環流程圖
一個可持續的良好模型需要測試流程上的配合,下圖是一個將線下性能測試與線上性能狀況相連接的閉環流程圖。
與傳統流程不同點在於:
l 性能測試的終點不再是發布上線,上線之后我們仍然會繼續跟蹤性能情況,並將結果用於下一次性能測試需求分析。
l 將線下與線上真正關聯起來,並通過換算系數實現性能預測,系數可動態調整的。
l 全程性能跟蹤,在生產環境中也加入性能監控,更快的解決線上性能問題。
1.2 TPS計算公式
ü 線下單機基線TPS =線上日均交易量 / 86400 / 機器數 * 160% * F
注:86400為一天的秒數。
注:假設硬件軟件環境條件大致相同。
注:F為影響因子,默認為1 。
關鍵系數160%的由來,簡單點講就是在每天約50%的時間里完成了80%的工作,80% / 50% = 160%。
該公式還只是最簡單場景的抽象,真實的情況可能會很復雜(詳見前面的數據示例分析),不過作為線下基線TPS來講具備很重要的參考意義。
線下基線TPS代表着為了達到線上的交易量,我們線下至少應該滿足的性能指標。我們在做性能測試和評估的時候,基線TPS是一定要體現並首先要達到的目標。
影響因子F是一個經驗值,也是需要不斷調優的,線上與線下的軟硬件環境不同都會導致F值的變化,甚至不同的業務線可以有不同的值。當我們的性能沙箱建立、性能閉環成型之后,會更加穩定下來。
1.3 影響因子
我們的計算公式是建立在假設硬件軟件環境條件大致相同的基礎上。但是在現實中,線上生產環境與線下測試環境總會難以避免的出現不一樣的情況,當出現不一致的情況后我們如何來估算?這里我們很難給出准確的推算公式,但是我們列出了可能的影響因素:
影響因子 |
吞吐率(TPS) |
響應時間(RT) |
硬件環境 |
||
CPU核數越多 |
越高 |
可能越低 |
CPU頻率越高 |
可能越高 |
越低 |
CPU支持64位指令 |
越高 |
可能越低 |
內存越大 |
可能越高 |
可能越低 |
磁盤空間越大 |
不明顯 |
不明顯 |
磁盤速率越高 |
可能越高 |
可能越低 |
網卡速率越高 |
越高 |
越低 |
服務器品牌 |
未知 |
未知 |
顯卡性能越高 |
無影響 |
無影響 |
軟件環境 |
||
操作系統 |
首選Linux |
首選Linux |
Linux版本越高 |
不一定(2.6以上) |
不一定(2.6以上) |
JDK版本越高 |
不明顯(1.6) |
不明顯(1.6) |
SWAP分區越高 |
不一定 |
不一定 |
與其他服務共用 |
具體分析 |
具體分析 |
業務特點(計算型、IO型) |
具體分析 |
具體分析 |
1.4 響應時間
ü 后端核心服務響應時間不超過100ms
ü 后端一般服務響應時間不超過300ms
ü 前端用戶頁面加載時間不超過3s
注:這里是指平均響應時間。但性能測試報告必須給出最大、最小、平均、方差等數值。
1.5 穩定性要求
ü 確保零崩潰, 99.9% 的穩定性。
零崩潰是指在任何非外部原因的情況下,不管運行多長時間,都不能出現程序崩潰的情況。
99.9%的穩定性,意味着每千條交易中只能容許一條出錯,也意味着任何可能導致穩定性不達標的改進都需要慎重考慮。比如我們引入一種新的技術能使TPS增大50%,但是穩定性下降到97%,那么這可能也不能接受。
1.6 性能測試環境要求
為了更准確的預測性能,我們必須盡可能的保證性能測試環境的穩定。
ü 性能測試環境要求真實的物理機,一般不能是虛擬機。
ü 壓力工具與被測環境不能在同一台機器部署。
ü 盡可能的利用晚上無人操作的時間來做性能測試。
測試環境准備是一個很重要又很繁瑣的工作,它的效率提升依賴於我們的環境搭建平台的建設。
1.7 並發量和吞吐量(TPS)之間的關系
並發量(或叫並發用戶數):是指同一時間點對業務功能同時操作的用戶數。
吞吐量(TPS):一段時間內系統處理用戶的請求數量。
雖然兩者關系並不緊密,但是往往會有同學將它們搞混淆。其實我們可以用多線程模型來解釋他們,並發量就相當於線程數,吞吐量就是所有線程處理請求數之和。
通常我們做性能測試主要考察和評估的是TPS,而並發量是一個相對較虛的概念,比如我們說一個系統支持同時1k人操作,一般不在評估的范圍內。
1.8 線上性能數據采集
為了閉環需要,線上抽樣一台機器,采集每天的PV數據,每隔5分鍾采集一次,每天就有60/5 * 24 = 288個點。每個點需要采集Linux資源、JVM、IO以及PV數據,這些數據將成為將來性能評估的重要依據。平台化也是趨勢,目前可以依賴公司的性能平台以及監控平台去觀察統計數據。定期消除異常數據噪音,以月為單位可觀察規律變化。
2. 性能測試需求分析
對於性能測試,一般來說工具的使用不是大的問題,問題是前期的需求分析,要不要做性能測試?性能測試的目的是什么?要做或不做性能測試的理由是什么?如何來做性能測試?這些問題的答案都是通過分析性能測試需求得到的。以下將闡述性能需求分析的一些基本方法。
2.1 業務調研
為了合理評估與制定系統的性能指標,業務調研是一個必備的過程,業務調研主要包含以下幾個方面的內容:
系統信息調研
- 系統類型:系統的基本特性,如交易處理型系統、數據處理型系統等
- 架構部署:系統的整體架構、服務器部署方式
- 技術信息:系統運行平台、數據庫產品、使用的中間件、協議及通訊方式等
- 業務信息:支持的業務類型、業務范圍與功能、與其它系統的業務關系等
- 系統歷史運行情況:目標TPS,用戶數、PV等數據
- 系統數據規模:將來系統使用規模,歷史系統數據規模
業務信息調研
- 基本業務功能:系統的基本業務概念以及系統的業務種類與具體功能
- 關鍵業務邏輯處理流程:關鍵業務的業務流程、交易路徑、交易數據、交易流程與時序圖
- 交易列表:調查業務系統全部交易清單,了解交易的組合關系、執行順序等
- 交易量信息:在不同時間粒度下統計單個交易處理量以及總交易量信息
- 業務目標/業務拓展計划:目前的生產業務量和用戶數以及系統預期業務目標和本次測試預期業務指標
文檔資料調研
- 功能規格說明書
- 系統設計文檔
- 生產運營統計
- 前期系統測試資料
業務調研涉及到的角色有以下幾個:業務人員、開發人員、客戶、產品人員、運維人員、DBA等。
通過業務調研至少可以得到以下幾個方面的產出:
- 項目背景
- 系統架構說明
- 系統拓撲說明
- 測試范圍說明
- 交易路徑描述
- 需要測試的特性
- 不需要測試的特性
2.2 性能需求評估
在實施性能測試之前,需要對被測項目做相應的評估。主要目的是明確是否需要做性能測試和確立性能點,明確該測什么、期望值是多少。測試期望值也會根據情況評估,要求被測系統能滿足將來一定時間段的壓力。判斷是否進行性能測試可以從以下幾個方面進行思考:
a、從業務角度來分析,如果一個項目上去后使用的人數比較多,量比較大,就有做性能測試的必要,反之,如果一個項目上線后,沒有幾個人在用,無論系統多大,設計如何復雜,並發性的性能測試是沒有必要做的,前期可以否決。
b、從系統架構角度來分析,如果一個系統采用的框架是老的系統框架,只是在此框架上增加一些應用,其實是沒有必要做性能測試。如果一個系統采用的是一種新的框架,可以考慮做負載測試。
c、從實時性角度來分析,如果一個項目要求某個功能的響應時間,這個有作並發測試的可能性,在大並發量的場景下,查看這個功能的響應時間。
d、從數據庫角度分析,很多情況下,性能測試是大數據量的並發訪問、修改數據庫,而瓶頸在於連接數據庫池的數量,而非數據庫本身的負載、吞吐能力。這時,可以結合DBA的建議,來決定是否來做性能測試。
如果要進行性能測試,接下來我們就需要確定相應的性能點。主要從以下 4 個維度進行確定:
- 關鍵業務。
首要維度,是確定被測項目是否屬於關鍵業務,有哪些主要的業務邏輯點,特別是跟交易相關的功能點。例如快捷簽約、交易等接口。如果項目(或功能點)不屬於關鍵業務(或關鍵業務點),則可轉入第二、三、四個維度。
2. 日請求量。
第二個維度,是界定被測項目各功能點的日請求量。如果日請求量很高,系統壓力很大,而且又是關鍵業務,該項目需要做性能測試;而且其關鍵業務點,可以被確定為性能點。
3. 邏輯復雜度。
第三個維度,是判定被測項目各功能點的邏輯復雜度。如果一個主要業務的日請求量不高,但是邏輯很復雜,則也需要通過性能測試。原因是,在分布式方式的調用中,當某一個環節響應較慢,就會影響到其它環節,造成雪崩效應。
4. 運營推廣計划。
第四個維度,是根據運營的推廣計划來判定待測系統未來的壓力。未雨綢繆、防患於未然、降低運營風險是性能測試的主要目標。被測系統的性能不僅能滿足當前壓力,更需要滿足未來一定時間段內的壓力。因此,事先了解運營推廣計划,對性能點的制定有很大的作用。
例如,運營計划做活動,要求系統每天能支撐多少 PV、多少 UV,或者一個季度后,需要能支撐多大的訪問量等等數據。當新項目(或功能點)屬於運營重點推廣計划范疇之內,則該項目(或功能點)也需要做性能測試。
以上 4 個評估維護,是相輔相成、環環相扣的,它們合成一個維度集。在實際工作中應該具體問題具體分析。例如,當一個功能點不滿足以上 4 個維度,但又屬於內存高消耗、CPU高消耗時,也可列入性能測試點行列。
2.3 性能測試指標
性能需求分析一個很重要的目標就是需要確定后期性能分析用的性能指標,性能指標有很多,可以根據具體項目選取和設定,而具體的指標值則需要根據業務特點和上述的一些方法進行設定。性能評估模型章節中也給了一些指標換算的基本方法。
2.3.1 性能指標分析
判斷一個系統的性能通常會取決於這三個最重要的性能指標:
ü 吞吐率(TPS)
ü 響應時間(RT)
ü 系統資源利用率(Load)
通常經驗告訴我們,它們三者的趨勢會如下圖所示:
當處於輕負載區的時候,壓力有多大,吞吐率就有多大。
一旦進入重負載區,就算是再怎么努力可能也會是白費。
如果到了崩潰區,那我們的努力就開始有反效果。
同樣,對於我們做性能測試來講,我們的目的就是找出這三個區域的分界線來。
所以在設計上,我們需要不斷地遞增負載來觀察和評估系統性能情況。
比如下表(以下數據為偽造):
TPS |
RT(AVG/MIN/MAX) |
Load(cpu idle/mem/io) |
100 |
50/15/80 |
93/8/2 |
200 |
50/18/90 |
91/8/2 |
400 |
55/18/145 |
87/9/4 |
800 |
130/25/560 |
70/10/14 |
1500 |
250/58/4488 |
48/11/75 |
可以看出,TPS低於400的時候基本屬於輕負載區,400到800之間屬於重負載區,高於800基本上屬於崩潰區了。
2.3.2 業務性能指標
指標名 |
指標說明 |
采集方法 |
並發用戶數 |
在同一時刻與服務器進行了交互的在線用戶數量 |
Jmeter/loadrunner |
響應時間 |
客戶發出請求到得到響應的整個過程的時間。一般他可以分為三部分:呈現時間,數據傳輸時間和系統處理時間 |
Jmeter/loadrunner |
吞吐量 |
一次性能測試過程中網絡上傳輸的數據量的總和 |
Jmeter/loadrunner |
每秒處理事務數(TPS) |
每秒鍾系統能夠處理事務或交易的數量,它是衡量系統處理能力的重要指標。 |
Jmeter/loadrunner |
點擊率 |
點擊率可以看做是TPS的一種特定情況。每秒鍾用戶向web服務器提交的HTTP請求數。 |
Jmeter/loadrunner |
事務成功率 |
本次測試中出現成功的事務數量/事務的總數 |
Jmeter/loadrunner |
2.3.3 應用服務器及硬件性能指標
指標名 |
指標說明 |
采集方法 |
CPU占用率 |
對一個時間段內CPU使用狀況的統計。 建議:<75% |
nmon/vmstat/top |
Load Average |
一段時間內CPU正在處理以及等待CPU處理的進程數之和的統計信息,也就是CPU使用隊列的長度的統計信息。 建議:<0.7*CPU個數*核數 |
top/uptime |
Paging rate |
內存頁交換率,建議<80% |
nmon/vmstat/top |
磁盤I/O |
Iowait<30% |
nmon/iostat/sar |
SWAP |
有沒有交換頁面 |
nmon |
Tomcat啟動的總線程數 |
關注線程數會不會無限制增長、線程數量是否足夠 |
Top |
Full GC次數 |
關注Full GC次數,以及Full GC后內存占用有沒有明顯增長 |
Jstat/jconsole |
JVM內存使用與回收 |
|
Jstat/jconsole |
JDBC監控 |
|
Jprofiler |
Exception日志監控 |
監控壓力過程中是否有異常日志產生 |
Tail&grep |
2.3.4 數據庫性能指標
指標名 |
指標說明 |
采集方法 |
DB cpu占用率 |
數據庫cpu利用率,建議<70% |
nmon |
DB load |
數據庫服務器負載 |
Top |
DB mem |
內存使用是否平穩 |
Nmon |
DB 磁盤與I/O |
I/O是數據庫性能一個非常重要的因素,建議IOwait<30% |
Nmon/iostat/sar |
數據庫線程數 |
|
Top |
緩存命中率 |
點擊率可以看做是TPS的一種特定情況。每秒鍾用戶向web服務器提交的HTTP請求數。 |
AWR |
共享池命中率 |
假如這個值低於95%就要考慮調整應用(改寫多為變量綁定)或者增加內存 |
AWR |
Top 耗時 sql |
找出性能較差的sql,進行優化 |
AWR |
2.3.5 性能指標參考
在確定性能指標的時候,可以參考一下表中對應的數值。
指標項 |
優秀 |
中等 |
差 |
TPS |
TPS >=100 |
50<TPS <100 |
TPS<=50 |
響應時間 |
RT<=200ms |
200ms<RT<500ms |
RT>=500ms |
響應長度 |
ResponseSize<=100KB |
100KB<ResponseSize<500KB |
ResponseSize>=500KB |
CPU |
CPU<=75% |
75%<CPU<80% |
CPU>=80% |
Load |
Load<=2 |
2<Load<5 |
Load>=5 |
FullGC |
FullGC<=1 |
1<FullGC<10 |
FullGC>=10 |
DBQPS |
DBQPS<5*TPS |
5*TPS<DBQPS<10*TPS |
DBQPS>=10*TPS |
慢SQL數量 |
慢SQL=0 |
慢SQL=1 |
慢SQL>=2 |
2.3.6 壓力與容量預估
首先,由產品同學給出線上交易量預估,並根據TPS線上線下換算公式,得出線下TPS基線。
ü 達標目標:TPS基線必須在輕負載區區域內。
面對數據庫或第三方依賴,需要評估可能的瓶頸,數據庫最好使用真實的並容量與線上最大值保持一致,因為數據庫成為瓶頸的可能性比較大。
假如我們有一個數據庫線上有數據100G,分了4個庫,每個庫128張表,平均每張表有195M數據,約15w條數據。性能上我們可以只構造一個庫的情況,約25G的數據。我們在做性能測試之前必須提早做好這25G的數據。
其他第三方依賴如果已經做過良好的性能評估,比如內部消息系統服務,那么我們可以適當采用性能樁的方式來替代真實后端。
注:不管是壓力還是容量,都離不開具體的業務分析,只能這樣才能把性能測試做到最完美。