JVM飆高排查腳本-結構分析

jopen 10年前發布 | 6K 次閱讀 Java開發

該文章來自于阿里巴巴技術協會(ATA)精選文章。

大家都有過遇到線上程序LOAD突然狂飆的場景,要排查到為何狂飆,我們當務之急就是要找到導致CPU飆升的原因。如果是進程級的應用,如Nginx、Apache等都還比較容易排查,但如果是JVM中的某個線程導致的,估計有人就要開始抓瞎了。

很多人都或多或少的知道有這么一個腳本,能幫你大致定位到現場導致LOAD飆升的JVM線程,腳本大概如下。

#!/bin/ksh

# write by    : oldmanpushcart@gmail.com
# date        : 2014-01-16
# version     : 0.07

typeset top=${1:-10}
typeset pid=${2:-$(pgrep -u $USER java)}
typeset tmp_file=/tmp/java_${pid}_$$.trace

$JAVA_HOME/bin/jstack $pid > $tmp_file
ps H -eo user,pid,ppid,tid,time,%cpu --sort=%cpu --no-headers\
        | tail -$top\
        | awk -v "pid=$pid" '$2==pid{print $4"\t"$6}'\
        | while read line;
do
        typeset nid=$(echo "$line"|awk '{printf("0x%x",$1)}')
        typeset cpu=$(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使用占比高的線程

ps H -eo user,pid,ppid,tid,time,%cpu --sort=%cpu

 

alt

 

列說明

USER:進程歸屬用戶

PID:進程號

PPID:父進程號

TID:線程號

%CPU:線程使用CPU占比(這里要提醒下各位,這個CPU占比是通過/proc計算得到,存在時間差)

步驟3:合并相關信息

我們需要關注的大概是3列:PID、TID、%CPU,我們通過PS拿到了TID,可以通過進制換算10-16得到jstack出來的JVM線程號?

typeset nid="0x"$(echo "$line"|awk '{print $1}'|xargs -I{} echo "obase=16;{}"|bc|tr 'A-Z' 'a-z')

最后再將ps和jstack出來的信息進行一個匹配與合并。終于,得到我們最想要的信息

alt

 

 

適用范圍說明

看似這個腳本很牛X的樣子,能直接定位到最耗費CPU的線程,開發再也不用擔心找不到線上最有問題的代碼~但,且慢,姑且注意下輸出的結果,State: WAITING 這是這個啥節奏~

alt

這是因為ps中的%CPU數據統計來自于/proc/stat,這個份數據并非實時的,而是取決于OS對其更新的頻率,一般為1S。所以你看到的數據統計會和jstack出來的信息不一致也就是這個原因~但這份信息對持續LOAD由少數幾個線程導致的問題排查還是非常給力的,因為這些固定少數幾個線程會持續消耗CPU的資源,即使存在時間差,反正也都是這幾個線程所導致。

這里分享下淘寶內部經常排查到的幾個有問題線程,大家如果用到了又遇到LOAD突然飆高,可以優先懷疑他們。

Forest、CatServer、Notify

轉自:http://yq.aliyun.com/articles/55


來自: http://blog.csdn.net//kingzone_2008/article/details/50411670

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!