Tomcatスレッド状態確認スクリプト

Tomcatもビジーになってくると、スレッドが効率的に利用されているのかが気になってくる。それにはスレッド状態を見てやればよい。

Linux kernel 2.6.Xでは、procfsを覗いてやると、各プロセス中のスレッド状態を取得することが出来る。Tomcatのスレッド状態をコマンド一発で取得できればうれしいね。ということでシェルスクリプトを作ってみた。

 

#! /bin/sh
#
# tomcatstat.sh : Obtain thread statuses of Tomcat
#
# Copyright(c) 2012 Ryuichi Kurishima
#
# This script is BSD licensed.
#


CNT_R=0
CNT_S=0
CNT_D=0
CNT_Z=0
CNT_T=0
CNT_W=0
CNT_ALL=0
CNT_UNKOWN=0



progName=`basename $0`

banner() {
    echo "-------------------------"
    echo " $progName : Check for thread statuses of Tomcat"
    echo ""
    echo " Copyright(c) 2012 Ryuichi Kurishima, all rights reserved."
    echo ""
    echo " This script is BSD licensed."
    echo ""
    echo "-------------------------"
}


#
# Main body.
#
banner

# Identify Tomcat's PID

pid=`ps -ef|grep java|grep Bootstrap|grep -v grep|gawk '{print $2}'`


if [ x"$pid" = x ]; then
    echo "Tomcat is not found. Quitting."
    exit 1
fi

echo "Tomcat PID : ${pid}"
echo "-*-*-*-*-*-*-"

threads=`ls /proc/${pid}/task`

for thread in $threads
do
    path=/proc/${pid}/task/${thread}/stat
    state=`cat $path|gawk '{print $3}'`

    # Refer to procfs man page.
    if [ x"$state" = x"R" ]; then
        desc="Running"
        CNT_R=`expr ${CNT_R} + 1`
    elif [ x"$state" = x"S" ]; then
        desc="Interruptibe Sleep"
        CNT_S=`expr ${CNT_S} + 1`
    elif [ x"$state" = x"D" ]; then
        desc="Uninterruptible Disk Sleep"
        CNT_D=`expr ${CNT_D} + 1`
    elif [ x"$state" = x"Z" ]; then
        desc="Zombie"
        CNT_Z=`expr ${CNT_Z} + 1`
    elif [ x"$state" = x"T" ]; then
        desc="Traced or Stopped (on a signal)"
        CNT_T=`expr ${CNT_T} + 1`
    elif [ x"$state" = x"W" ]; then
        desc="Paging"
        CNT_W=`expr ${CNT_W} + 1`
    else
        desc="Unkown Status"
        CNT_UNKOWN=`expr ${CNT_UNKOWN} + 1`
    fi
    CNT_ALL=`expr ${CNT_ALL} + 1`
    echo "Thraed ID : ${thread}, state = '${state}', description = '${desc}'"
done

echo "-*-*-*-*-*-*-"
echo "State 'R' (Running) count : ${CNT_R}"
echo "State 'S' (Interruptible Sleep) count : ${CNT_S}"
echo "State 'D' (Uninterruptible Disk Sleep) count : ${CNT_D}"
echo "State 'Z' (Zombie) count : ${CNT_Z}"
echo "State 'T' (Traced or Stopped) count : ${CNT_T}"
echo "State 'W' (Paging) count : ${CNT_W}"
echo "Unkown State : ${CNT_UNKOWN}"
echo ""
echo "Threads count (ALL) : ${CNT_ALL}"

実施例は以下の通り。

user@server$ tomcatstat.sh
-------------------------
tomcatstat.sh : Check for thread statuses of Tomcat

Copyright(c) 2012 Ryuichi Kurishima, all rights reserved.

This script is BSD licensed.

-------------------------
Tomcat PID : 2275
-*-*-*-*-*-*-
Thraed ID : 2275, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2316, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2317, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2318, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2319, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2320, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2321, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2322, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2323, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2416, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2474, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2475, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2547, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2550, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2551, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2552, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2553, state = 'S', description = 'Interruptibe Sleep'
Thraed ID : 2554, state = 'S', description = 'Interruptibe Sleep'
-*-*-*-*-*-*-
State 'R' (Running) count : 0
State 'S' (Interruptible Sleep) count : 18
State 'D' (Uninterruptible Disk Sleep) count : 0
State 'Z' (Zombie) count : 0
State 'T' (Traced or Stopped) count : 0
State 'W' (Paging) count : 0
Unkown State : 0

Threads count (ALL) : 18
user@server$

ウチのサーバーのTomcatはヒマだから、全部スリープ中なのだ。

スレッド状態には、procfsのmanページによると、以下の状態がある。

R (Running) : 実行状態。この状態のスレッドばかりならば、フル稼働中というわけだ。働き者ぉ~!
S (Interruptible Sleep) : 割り込み可能なスリープ状態。割り込み可能とは、つまり、いつでも処理を担当することが出来るということ。手持ち無沙汰なんだね。
D (Uninterrutible Disk Sleep) : 割り込み不可能なディスクアクセス状態のスリープ。この状態が長く続くならば、何かディスクI/Oパフォーマンス上の問題があるのかも。
Z (Zombie) : スレッドのゾンビ状態。スレッド実行終了後、他の任意の「仲間スレッド」がpthread_join()してやらないと、ずっとこの状態で残ってしまうよ。プロセスのゾンビと違って、確かスレッドゾンビの場合はリソースをつかんだままだったような。。。
T (Traced or Stopped) : スレッドがトレース状態かストップ状態となっている。デバッガがプロセスにアタッチしていることがなければ、普通はこういうことはない。
W (Paging) : 物理ページへ"W"riteしているのだろう。Linuxはオン・デマンド・ページング(またはコピー・オン・ライトともいうね)なので、仮想メモリの書き換えが起こる時点で実際に物理ページを新しく割り当てる。一時的にこの状態ならば問題はないだろうが、ずっとこの状態であるならば、カーネルによるページのリクレーム処理が長引いているのかもしれない。Linuxはページが足りなくなると一気にガツンとリクレームするからね。

たとえば、Tomcatのスレッドがスリープ状態なのにリクエストの滞留(処理待ち)が発生しているならば、KeepAlive等によってコネクションを握ってしまっているクライアントがいるということだ。Tomcatコネクタのコネクションタイムアウト値(既定で60000ミリ秒=60秒)を2000ミリ秒=2秒程度に設定してやるとずっと具合がよくなる。これはちょっとしたTipsだよ。

コメントの投稿

(スタイル用のHTMLタグを使えます)