天天看點

Java應用CPU占用過高問題排查

問題分析:

如果Java應用程式把CPU 100%打滿,該怎麼辦呢?

JVM調優,一般都是在負載壓力測試情況下,對于單個節點提供服務出現瓶頸時,才會啟動性能調優,而JVM調優隻是其中的一部分。在進行JVM調優之前,我們一般都會進行CPU消耗的分析、記憶體消耗的分析、磁盤IO的分析、網絡IO的分析以及程式自身的問題。在這些名額都正常的情況下,才會轉向JVM的調優,主要是看記憶體大小配置設定是否合理,記憶體比例是否合理,結合系統特性對垃圾回收器是否合理,會對JVM進行閥值的更改(升帶閥值、JIT),通過打開JVM日志收集相關資料,往複這個過程。

通常性能瓶頸的表象是資源消耗過多,外部處理系統的性能不足,或者資源消耗不多,但程式的響應速度卻達不到要求。資源主要消耗在CPU、檔案IO、網絡IO、以及記憶體方面,機器的資源是有限的,當某資源消耗過多他,通常會造成系統的響應速度慢,資源消耗不多,但程式的響應速度仍達不到要求的主要原因是程式代碼運作效率不夠高、沒有充分使用資源或程式結構不合理。

CPU消耗過高分析

在Linux中,CPU主要用于中斷、核心以及使用者程序的任務處理,優先級為:中斷>核心>使用者程序

上下文切換

每個CPU(或多核CPU中的每核CPU)在同一時間隻能執行一個線程,Linux采用的搶占式排程,即為每個線程配置設定一定的執行時間,當達到執行時間、線程中有IO阻塞或高于優先級線程要執行時,Linux将切換執行的線程,在切換是要存儲目前線程的執行狀态,并回恢複是要執行的線程的狀态,這個過程就是上下文切換。

對于Java應用,典型的是在進行檔案IO操作、網絡IO操作、鎖等待或線程Sleep時,目前線程會進入阻塞或休眠狀态,進而出發上下文切換,上下文切換過多或造成核心占據較多的CPU使用,應用的響應速度下降。

運作隊列

每個CPU都維護了一個可運作的線程隊列,運作隊列值越大,意味着線程會消耗越長的是時間才能完成,建議控制每個CPU核上的運作隊列為1~3個。

使用率

CPU使用率為CPU在使用者程序、核心、中斷處理、IO等待以及空閑五個部分使用百分比,這五個值用來分析CPU消耗情況的關鍵名額。

建議使用者程序的 CPU 消耗/核心的 CPU 消耗的比率在 65%~70%/30%~35% 左右。

解決問題

思路:定位java服務進行、定位java線程、定位代碼塊

定位java服務程序

一個伺服器可能有多個java服務。通過top指令檢視是那個服務cpu使用率較高,記住CPU使用率較高的pid号:ps -aux | grep pid或者top -p pid

定位java線程

每個java服務中有很多線程在執行,先定位到那個線程CPU使用率較高,可以由下面3種方式:

1.通過ps指令

ps H-eo pid,tid,%cpu --sort=%cpu | grep <PID>      

2.通過top指令

top -H -p <PID>      

3.通過ps指令

ps -mp <PID> -o THREAD,tid,time      

通過上面的方式任意一種指令,找到CPU使用率較高的線TID後,執行下面的指令:

printf "0x%x\n" <線程ID>      

目的:将線程TID轉換為16進制,為後面查找jstack日志做準備

jstack -l <pid> >> jstackLog.out