1. 程式人生 > 實用技巧 >JVM飆高排查指令碼-結構分析

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

alt

列說明

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出來的資訊進行一個匹配與合併。終於,得到我們最想要的資訊

alt

適用範圍說明

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

alt

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

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

Forest、CatServer、Notify



轉載於:https://blog.51cto.com/wozhangkun/1793307