【性能測試】常見的性能問題分析思路(二)案例&技巧
上一篇介紹了性能問題分析的診斷的基本過程,還沒看過的可以先看下【性能測試】常見的性能問題分析思路-道與術,精鍊總結下來就是,當遇到性能問題的時候,首先分析現場,然後根據現象去查找對應的可能原因,在通過對應的方法和工具去定位問題。
本篇來給出個具體實際工作中的案例,以及會簡單說一下一種性能分析工具的使用技巧,加深這方面的認知和學習。
案例分析
背景
對某個項目(內部項目脫敏)進行壓測的時候出現了內存泄漏的問題,經過發現問題-分析現象和過程-定位問題,排查出根因是定時任務引發的內存泄漏,因此把整個分析過程分享出來,做個類型性能缺陷的參考,也作為分析過程的一個實際操作案例。
問題現象
計稅某接口/finance-xxxxx-center/xxxxx/incomeCalculate接口,壓測過程中,通過監控發現,服務器的CPU每隔一段時間有規律波動,內存由60%上漲至85%,更奇怪的是當停止壓測後,CPU依舊有規律的尖刺波動,服務器內存佔用率一直居高在85%沒有回收。
分析過程
從上述CPU佔用圖上看,一開始的思路是以為MQ消息消費導致的,去阿里雲觀察MQ消費情況。
從兩個方面驗證:第一讓研發去review代碼,是不是有定時任務在執行檢查執行頻率,第二,我通過打印CPU尖刺時間段線程dump,查看尖刺時CPU佔用的線程,定位到引起CPU尖刺的就是定時任務線程和GC回收線程。
到這裡之後還有一個點需要分析,那就是服務器的內存為什麼會持續上升?上升之後為什麼沒回收?需要確認內存這個現象是不是導致CPU尖刺的定時任務引起。
首先,去應用服務器上看了GC情況,發現沒有尖刺的時候YGC幾乎沒有,但是當CPU尖刺時間段,就有頻繁的YGC,除了單次GC時間730ms不正常,其他的算正常。
所以需要進一步找內存上漲,內存不釋放原因。
打印壓測停止後存活對象的內存堆dump,通過mat工具分析。
從工具上看有三處疑似內存泄漏,主要關注suspect1,通過GCroot分析。
進一步確認是quartz引起的 對象不釋放。
接下來,我們驗證猜想,定時任務5分鐘執行一次,而且執行完一次可能不只5分鐘。
分兩步走,第一去看服務器日誌,當出現CPU尖刺的時候,觀察job跑批的時間,發現單次job啟動後,由於數據量大,在5分鐘之內無法跑完,日誌一直刷,出現任務浪打浪現象
到這裡基本可以確定是定時任務造成的,那個數量是太大了,一次性撈出來的數據太多導致5分鐘之內執行不完任務,然後5分鐘後job又重新啟動,形成job日誌一直在刷,然後對象的引用無法清除,導致大對象佔用內存不能釋放。
接下來我們在通過再次壓測驗證,修改定時任務頻率為1個小時,重啟服務器,繼續壓測計稅接口,發現CPU沒有尖刺出現,內存也沒有明顯上升,然後把定時任務頻率再改回5分鐘,發現跑任務的時候,內存又繼續上去了,而且一直維持在85%的高位,到此驗證完畢。
ARTHAS
本工具是阿里開源的Java診斷工具,很多研發和性能分析同學使用,是一把通過探測系統深度問題的利器。由於本篇不是講解此工具,安裝,使用的就略了,敢興趣的參考Arthas(阿爾薩斯)吧[參考-1],這裡給一些交互截圖和在性能測試問題分享一些使用技巧
如了解系統狀態信息
如查看Profiler/FlameGraph/火焰圖
性能分析案例一些使用方法技巧
-
先用thread -n 10 找出線程堆棧中程序運行的類與方法
-
Thread –b 檢測是否有線程鎖
-
接着sc -d com.poizon.infr.user.core.service.util.HttpUtil.doHttpPost,查找類
-
然後 sm -d com.poizon.infr.user.core.service.util.HttpUtil包下的方法
-
再然後trace com.poizon.infr.user.core.service.util.HttpUtil doHttpPost ‘#cost > 10’方法耗時
-
trace com.poizon.infr.user.core.service.controller.UnionLoginController unionLogin ‘#cost > 50’ -n 3
-
jad –source-only com.poizon.infr.user.core.service.util.HttpUtil.doHttpPost ,反編譯出懷疑的源代碼進行分析
-
profiler -e cpu -d 300 –format svg start 火焰圖
【註解&參考】
[參考-1] //arthas.aliyun.com/doc/
原稿分享:禧子
優化編輯:大奇