JVM飆高排查指令碼-結構分析
JVM飆高排查指令碼-結構分析
摘要:該文章來自於阿里巴巴技術協會(ATA)精選文章。 大家都有過遇到線上程式LOAD突然狂飆的場景,要排查到為何狂飆,我們當務之急就是要找到導致CPU飆升的原因。如果是程序級的應用,如Nginx、Apache等都還比較容易排查,但如果是JVM中的某個執行緒導致的,估計有人就要開始抓瞎了。 很多人都...
該文章來自於阿里巴巴技術協會(ATA)精選文章。
大家都有過遇到線上程式LOAD突然狂飆的場景,要排查到為何狂飆,我們當務之急就是要找到導致CPU飆升的原因。如果是程序級的應用,如Nginx、Apache等都還比較容易排查,但如果是JVM中的某個執行緒導致的,估計有人就要開始抓瞎了。
很多人都或多或少的知道有這麼一個指令碼,能幫你大致定位到現場導致LOAD飆升的JVM執行緒,指令碼大概如下。
#!/bin/ksh #writeby:[email protected] #date:2014-01-16 #version:0.07 typesettop=${1:-10} typesetpid=${2:-$(pgrep-u$USERjava)} typesettmp_file=/tmp/java_${pid}_$$.trace $JAVA_HOME/bin/jstack$pid>$tmp_file psH-eouser,pid,ppid,tid,time,%cpu--sort=%cpu--no-headers\ |tail-$top\ |awk-v"pid=$pid"'$2==pid{print$4"\t"$6}'\ |whilereadline; do typesetnid=$(echo"$line"|awk'{printf("0x%x",$1)}') typesetcpu=$(echo"$line"|awk'{print$2}') awk-v"cpu=$cpu"'/nid='"$nid"'/,/^$/{print$0"\t"(isF++?"":"cpu="cpu"%");}'$tmp_file done rm-f$tmp_file
現在我們就來拆解其中的原理,以及說明下類似指令碼的適用範圍。
步驟1:dump當前JVM執行緒,儲存現場
$JAVA_HOME/bin/jstack$pid>$tmp_file
儲存現場是相當的重要,因為問題轉瞬之間就會從手中溜走(但其實LOAD的統計機制也決定了,事實也並不是那麼嚴格)
步驟2:找到當前CPU使用佔比高的執行緒
psH-eouser,pid,ppid,tid,time,%cpu--sort=%cpu
列說明
USER:程序歸屬使用者
PID:程序號
PPID:父程序號
TID:執行緒號
%CPU:執行緒使用CPU佔比(這裡要提醒下各位,這個CPU佔比是通過/proc計算得到,存在時間差)
步驟3:合併相關資訊
我們需要關注的大概是3列:PID、TID、%CPU,我們通過PS拿到了TID,可以通過進位制換算10-16得到jstack出來的JVM執行緒號
typesetnid="0x"$(echo"$line"|awk'{print$1}'|xargs-I{}echo"obase=16;{}"|bc|tr'A-Z''a-z')
最後再將ps和jstack出來的資訊進行一個匹配與合併。終於,得到我們最想要的資訊
適用範圍說明
看似這個指令碼很牛X的樣子,能直接定位到最耗費CPU的執行緒,開發再也不用擔心找不到線上最有問題的程式碼~但,且慢,姑且注意下輸出的結果,State: WAITING 這是這個啥節奏~
這是因為ps中的%CPU資料統計來自於/proc/stat,這個份資料並非實時的,而是取決於OS對其更新的頻率,一般為1S。所以你看到的資料統計會和jstack出來的資訊不一致也就是這個原因~但這份資訊對持續LOAD由少數幾個執行緒導致的問題排查還是非常給力的,因為這些固定少數幾個執行緒會持續消耗CPU的資源,即使存在時間差,反正也都是這幾個執行緒所導致。
這裡分享下淘寶內部經常排查到的幾個有問題執行緒,大家如果用到了又遇到LOAD突然飆高,可以優先懷疑他們。
Forest、CatServer、Notify
轉載於:https://blog.51cto.com/wozhangkun/1793307