性能測試支付寶場景介紹
2013年雙11過程當中,促銷開啟的第一分鍾內支付寶的交易總額就突破了一億元,短時間內大量用戶涌入的情況下,如何保證用戶的支付順暢,是對支付寶應用系統的一個極大的挑戰。
支付寶的性能測試場景分為性能基線測試,項目性能測試。
任意一筆交易過來,我們都需要對交易進行風險掃描,對於有可能是賬戶盜用的交易,我們會把這筆支付直接拒絕掉,或者通過手機校驗碼等方式進行風險釋放。
我們有一個老的掃描平台A,現在需要構建一個新的掃描平台B,對A中關鍵技術進行升級,並增加額外的功能。掃描的策略是存儲在DB中的,需要通過發布來更新到應用服務器的內存中。
性能測試需求分析和方案制定
a. 需求挖掘
1),查看業務方的顯性需求。業務方給到的需求為平台B的分析性能要優於平台A的性能。除此之外無其它的需求。
2),挖掘隱性需求.了解業務架構,了解業務流程。為了保證掃描的性能,大量的存儲類的需求被設計為異步處理,但是結果類的掃描需要使用到前面落地的數據,那么在系統正常運行時是否會存在落地數據讀取不到的問題,在存儲抖動時是否會導致后續的分析掃描全部失效?
首先我們通過運維監控平台拿到平台A的分析性能,RT<130ms, TPS>35.
基於以上的需求挖掘,我們確認的性能測試場景為
-
掃描性能場景。(單場景)
-
發布性能場景。(單場景)
-
掃描過程中發布性能場景。(混合場景)
b. 技術方案
1).評估我們的系統架構,系統調到鏈路,定位可能存在問題的瓶頸點。
2).掌握詳細技術實現方案,了解具體技術方案可能存在的性能問題。
比如我們是否使用到了腳本動態編譯,是Java腳本還是groovy腳本。是否使用到了線程池等異步處理,系統冪等性是如何控制的,數據結構是如何存儲與讀取的,是決策樹還是圖型結構。
3).了解系統環境的差異,比如服務器位數、CPU、內存的差異,JDK版本及位數的差異。
基於以上的技術方案,我們確認了上述3個性能測試場景可能存在的性能問題
1. 掃描性能場景
技術方案為掃描引擎drools2升級到了drools5.
性能關注點為請求掃描RT,TPS是否滿足我們的需求;JVM Old區內存溢出,Old區內存泄露;GC 頻率過高。CPU使用率,load.
2. 發布性能場景
技術方案為規則DB撈取->規則加載->規則引擎切換->規則腳本編譯。
性能關注點為CPU使用率,load。JVM Perm區內存溢出,Perm區內存泄露,GC 頻率過高。GC 暫停應用時間。
3. 掃描過程中發布性能場景。
性能關注點為請求掃描RT,TPS。規則發布耗時,CPU使用率,load, JVM GC頻率。
c. 性能測試方案制訂
-
分布式壓測,參數自動化,使用單元測試腳本,接口測試腳本,jmeter腳本等進行壓測。
-
性能結果收集及統計。
- 性能測試通過標准。
基於以上的分析
1. 掃描性能場景
性能測試方案:
使用jmeter 腳本進行分布式壓測,一台master, 三台slaver. 參數自動構建,使用高斯定時器模擬真實場景。
使用jmeter 收集分析性能數據,使用nmon收集服務器性能數據,使用jconsole收集JVM數據。
通過標准:
RT<130ms, TPS>35.
JVM old 區內無內存泄露,無內存溢出。GC時間間隔>30min,暫停應用時間<150ms.
CPU<70%, load < core*1.5。
2. 發布性能場景
性能測試方案:
發布時間間隔時間限制從1min調整為3s, 更快的暴露問題。
使用單元測試類推送發布消息。
服務器shell 腳本收集發布模塊性能數據。
使用nmon收集服務器性能數據。
使用jconsole收集JVM數據。
通過標准:
JVM Perm 區內無內存泄露,無內存溢出。GC時間間隔>10min,暫停應用時間<200ms.
發布時間<30S
CPU<70%, load < core*1.5。
3.掃描過程中發布性能場景
性能測試方案:
使用jmeter腳本進行分布式壓測,同時提交發布請求進行發布。
同時使用掃描性能場景和發布性能場景收集數據功能。
通過標准:
RT < 掃描性能場景結果RT * 110%.
TPS > 掃描性能場景結果TPS * 90%.
發布時間 < 40s。
d. 發現的問題
1. 掃描性能場景
AVG RT = 473ms, CMS GC = 90ms, 應用暫停時間 = 1s, 因此測試未通過。
問題定位:
dump內存,使用ibm memory analyzer 分析。
確認cms gc的原因為drools引擎的finalize方法。Finzlize方法不能正確的釋放對象的引用關系,導致引用關系一直存在,無法釋放。
調優方案:
根據drools的升級文檔,升級drools引擎后解決此問題
2. 發布性能場景
CMS GC 回收失敗,內存無法被釋放,應用宕機。
問題定位:
GC回收比例為默認值68%,OLD區內存1024M,那么回收的臨界值為1024*0.68=696.32M。系統的JVM內存占用為500M,掃描策略相關的內存為120M,在切換的過程中,依賴額外的120M,因此只有在可用內存大於740M時才能正常回收。
解決方案:
調整JVM參數,擴大GC回收比例。
后續技術方案改造,使用增量發布解決此問題。
3. 掃描過程中發布性能場景
問題定位:
掃描平台發布流程,當首次請求進來時執行腳本動態編譯過程,由於腳本較多,因此所有腳本的動態編譯時間較長,在此過程中,進來的所有請求都會被hand住,造成大量超時
解決方案:
把腳本的動態編譯提前到首次請求調用進來之前,編譯通過后再切換掃描引擎,保證首次請求進來前一切准備就緒。
性能測試的執行和結果收集
3.1性能測試的執行
性能測試的執行需要具備以下幾個條件:施壓工具,測試環境以及對測試結果的收集工具。
3.1.1 施壓工具
我們先來說說施壓工具,支付寶使用的主流施壓工具是開源工具Apache JMeter,支持很多類型的性能測試:
-
Web - HTTP, HTTPS
-
SOAP
-
Database via JDBC
-
LDAP
-
JMS
-
任何用java語言編寫的接口,都可二次開發並調用。
支付寶大部分接口是webservice接口,基於soap協議,且都是java開發,所以使用jmeter非常方便,即使jemter工具本身沒有自帶支持的協議,也可以通過開發插件的方式支持。
3.1.2測試環境
測試環境包括被壓機和施壓機環境,需要進行硬件配置和軟件版本確認,保證系統干凈,無其他進程干擾,最好能提前監控半小時到1小時,確認系統各項指標都無異常。
另外除了被壓機和施壓機,有可能應用系統還依賴其他的系統,所以我們需要明確服務器的數量和架構,1是方便我們分析壓力的流程,幫助后面定位和分析瓶頸,2是由於我們線下搭建的環境越接近線上,測試結果越准確。但是通常由於測試資源緊張或者需要依賴外圍,例如銀行的環境,就會比較麻煩,通常我們會選擇適當的進行環境mock。當然,Mock的時候盡量和真實環境保持一致,舉個簡單的例子,如果支付寶端系統和銀行進行通信,線上銀行的平均處理時間為100ms,那么如果我們在線下性能測試時需要mock銀行的返回,需要加入100ms延遲,這樣才能比較接近真實的環境。
另外除了測試環境,還有依賴的測試數據也需要重點關注,數據需要關注總量和類型,例如支付寶做交易時,db中流水萬級和億級的性能肯定是不一樣的;還有db是否分庫分表,需要保證數據分布的均衡性。一般考慮到線下准備數據的時長,一般性能測試要求和線上的數據保持一個數量級。
3.1.3 測試結果收集工具
測試結果收集主要包括以下幾個指標:
響應時間、tps、錯誤率、cpu、load、IO、系統內存、jvm(java虛擬內存)。
其中響應時間、tps和業務錯誤率通過jemter可以收集。
Cpu、load、io和系統內存可以通過nmon或linux自帶命令的方式來監控。
Jvm可以通過jdk自帶的jconsole或者jvisualvm來監控。
總體來說,監控了這些指標,對系統的性能就有了掌握,同樣這樣指標也可以反饋系統的瓶頸所在。
性能測試瓶頸挖掘與分析
我們在上面一章中拿到性能測試結果,這么多數據,怎么去分析系統的瓶頸在哪里呢,一般是按照這樣的思路,先看業務指標:響應時間、業務錯誤率、和tps是否滿足目標。
如果其中有一個有異常,可以先排除施壓機和外圍依賴系統是否有瓶頸,如果沒有,關注網絡、db的性能和連接數,最后關注系統本身的指標:
-
硬件:磁盤是否寫滿、內存是否夠用、cpu的利用率、平均load值
-
軟件:操作系統版本、jdk版本、jboss容器以及應用依賴的其他軟件版本
-
Jvm內存管理和回收是否合理
-
應用程序本身代碼
先看下圖:是一般性能測試環境部署圖
1.
我們在定位的時候,可按照標注中的1、2、3數字依次進行排查,先排查施壓機是否有瓶頸、接着看后端依賴系統、db、網絡等,最后看被壓機本身,例如響應時間逐漸變慢,一般來說是外圍依賴的系統出現的瓶頸導致整體響應變慢。下面針對應用系統本身做下詳細的分析,針對常見問題舉1~2個例子:
4.1 應用系統本身的瓶頸
1. 應用系統負載分析:
服務器負載瓶頸經常表現為,服務器受到的並發壓力比較低的情況下,服務器的資源使用率比預期要高,甚至高很多。導致服務器處理能力嚴重下降,最終有可能導致服務器宕機。實際性能測試工作中,經常會用以下三類資源指標判定是否存在服務器負載瓶頸:
-
CPU使用率
-
內存使用率
-
Load
一般cup的使用率應低於50%,如果過高有可能程序的算法耗費太多cpu,或者某些代碼塊進行不合理的占用。Load值盡量保持在cpuS+2 或者cpuS*2,其中cpu和load一般與並發數成正比(如下圖)
內存可以通過2種方式來查看:
1) 當vmstat命令輸出的si和so值顯示為非0值,則表示剩余可支配的物理內存已經嚴重不足,需要通過與磁盤交換內容來保持系統的穩定;由於磁盤處理的速度遠遠小於內存,此時就會出現嚴重的性能下降;si和so的值越大,表示性能瓶頸越嚴重。
2) 用工具監控內存的使用情況,如果出現下圖的增長趨勢(used曲線呈線性增長),有可能系統內存占滿的情況:
-
如果出現內存占用一直上升的趨勢,有可能系統一直在創建新的線程,舊的線程沒有銷毀;或者應用申請了堆外內存,一直沒有回收導致內存一直增長。
4.2 Jvm瓶頸分析
4.2.1Gc頻率分析
對於java應用來說,過高的GC頻率也會在很大程度上降低應用的性能。即使采用了並發收集的策略,GC產生的停頓時間積累起來也是不可忽略的,特別是出現cmsgc失敗,導致fullgc時的場景。下面舉幾個例子進行說明:
1. Cmsgc頻率過高,當在一段較短的時間區間內,cmsGC值超出預料的大,那么說明該JAVA應用在處理對象的策略上存在着一些問題,即過多過快地創建了長壽命周期的對象,是需要改進的。或者old區大小分配或者回收比例設置得不合理,導致cms頻繁觸發,下面看一張gc監控圖(藍色線代表cmsgc)
由圖看出:cmsGC非常頻繁,后經分析是因為jvm參數-XX:CMSInitiatingOccupancyFraction設置為15,比例太小導致cms比較頻繁,這樣可以擴大cmsgc占old區的比例,降低cms頻率注。
調優后的圖如下:
2. fullgc頻繁觸發
當采用cms並發回收算法,當cmsgc回收失敗時會導致fullgc:
由上圖可以看出fullgc的耗時非常長,在6~7s左右,這樣會嚴重影響應用的響應時間。經分析是因為cms比例過大,回收頻率較慢導致,調優方式:調小cms的回比例,盡早觸發cmsgc,避免觸發fullgc。調優后回收情況如下
可以看出cmsgc時間縮短了很多,優化后可以大大提高。從上面2個例子看出cms比例不是絕對的,需要根據應用的具體情況來看,比如應用創建的對象存活周期長,且對象較大,可以適當提高cms的回收比例。
3. 疑似內存泄露,先看下圖
分析:每次cmsgc沒有回收干凈,old區呈上升趨勢,疑似內存泄露
最終有可能導致OOM,這種情況就需要dump內存進行分析:
-
找到oom內存dump文件,具體的文件配置在jvm參數里:
-XX:HeapDumpPath=/home/admin/logs -XX:ErrorFile=/home/admin/logs/hs_err_pid%p.log
-
借助工具:MAT,分析內存最大的對象。具體工具的使用這里就不再介紹。
文章來源於:InfoQ
文章作者 :付麗華 孫玉星