GrowthForecastでJBossの運用状況をグラフ化する
アプリケーションサーバでありがちなトラブルとしてDB接続プールの枯渇がある。原因はチューニングミスやSQLが長時間化してプールにコネクションが返って来ないなど色々とあるが、負荷試験時にモニタリングしておくと多くの問題は事前に検知・対処できる。JBossAS7以降、JBossにはHTTP API経由でサーバの運用状況を示すjsonを取得できる便利な機能がある。今回は、この機能を使って特にトラブルが起こりやすいデータソースの状況を取得し、GrowthForecastでグラフ化できないか考える。
JBossのHTTP 管理API
デフォルトでポート9990からアクセスできる。アクセスには認証が必要で、add-user.shで作成した管理ユーザのアカウントを使う。
以下の例ではデータソース名『PostgresDS』の状態をjson形式で取得する。
curl --digest -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-resource", "include-runtime":"true" , "address":["subsystem","datasources", "data-source", "PostgresDS", "statistics", "pool"], "json.pretty":1}' -u username:password -o datasource.json
結果は以下の通り。
{ "outcome" : "success", "result" : { "ActiveCount" : "25", "AvailableCount" : "25", "AverageBlockingTime" : "65", "AverageCreationTime" : "117", "CreatedCount" : "25", "DestroyedCount" : "0", "InUseCount" : "0", "MaxCreationTime" : "335", "MaxUsedCount" : "25", "MaxWaitCount" : "19", "MaxWaitTime" : "220", "TimedOut" : "0", "TotalBlockingTime" : "83135", "TotalCreationTime" : "2940" } }
他にも以下のような項目がjson形式で取得できる。
curl --digest -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-resource", "include-runtime":"true" , "address":["subsystem","transactions"], "json.pretty":1}' -u username:password -o transaction.json
- スレッドプールの動作状況(動作スレッド数、平均/最大プールからの取得待ち時間)
curl --digest -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-resource", "include-runtime":"true" , "address":["subsystem","threads","blocking-bounded-queue-thread-pool", "http-executor"], "json.pretty":1}' -u username:password -o threadpool.txt
- Javaヒープ
curl --digest -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-resource", "include-runtime":"true" , "address":["core-service","platform-mbean", "type", "memory"], "json.pretty":1}' -u username:password -o javaheap.json
他の例については、middle ware magicの記事が参考になると思う。
運用状況をグラフ化する
運用環境ではJP1やzabbixなどの監視ツールがあるシステムでも、負荷試験を行うようなテスト環境にはない場合も多いと思う。定期的に取得したデータを簡易にグラフ化するために、Web記事で良く見かけるGrowthForecastを使った。
このツールは以下のようにHTTP POSTするだけで、手軽にWebアクセスできるグラフが作成できてとても便利。
# http://example.com/api/:service_name/:section_name/:graph_name curl -F number=10 http://localhost:5858/api/MyJBoss/datasource/InUseCount
今回はシェルスクリプトで管理APIからjson形式でデータソースの動作状況を取得し、GrowthForcastに向けてPOSTすることでグラフを作成する。絵にすると以下のような構成を作る。
1. 監視対象項目を考える
一口にデータソースといっても、取得できる項目は色々とあるため、今回は以下の4項目を対象とした。
項目 | 説明 |
---|---|
AverageBlockingTime | コネクション取得に関する平均ブロック時間 |
InUseCount | 現在のコネクション使用数 |
MaxUsedCount | 最大コネクション使用数 |
MaxWaitTime | 最大コネクション取得待ち時間 |
特にInUseCountが常に上限に張り付いていたり、AverageBlokingTimeが1秒を超えるような状態は異常な状態と判断しても良いと思う。遅いSQLがコネクションを使用し続けているか、同時並列処理数に対してコネクション数が少なすぎる可能性が高い。
2. GrowthForecastのセットアップ
公式サイトの手順参照のこと。
growthforecast.pl --data-dir /home/test/growthforecast を実行して、GrowthForecastが起動するまで進める。
3. スクリプトを書く
少し長いが、手元で試しに作ってみたソースを以下に示す。
大まかな流れ。
jqはコマンドラインベースで、jsonから任意のプロパティ文字列を取得するのに便利なツール。bashではjsonが扱いにくいので、取得したjsonから例えばInUseCount(現在のコネクション使用数)などのプロパティを取得するために使った。
/home/test/monitor.sh
#!/bin/sh # JBossの管理ユーザ名とパスワード(add-user.sh) USER= PASSWORD= JBOSS_HOME=/home/test/jboss-as-7.1.1.Final TIME=`date +%Y%m%d%H%M%S` END_POINT=http://localhost:9990/management LOG_DIR=${JBOSS_HOME}/standalone/log/runtime/${TIME} APP_NAME=PerformanceTest GROWTH_FORCAST_ENDPOINT=http://localhost:5125/api/${APP_NAME} mkdir -p ${LOG_DIR} # JBossの管理APIよりデータソース運用状況の取得 curl --digest -D - ${END_POINT} --header "Content-Type: application/json" -d '{"operation":"read-resource", "include-runtime":"true" , "address":["subsystem","datasources","data-source","PostgresDS","statistics","pool"], "json.pretty":1}' -u ${USER}:${PASSWORD} -o ${LOG_DIR}/datasource.json 1>/dev/null 2>/dev/null # jsonから各種データを抽出する InUseCount=`/usr/local/bin/jq ".result .InUseCount | tonumber" ${LOG_DIR}/datasource.json` MaxUsedCount=`/usr/local/bin/jq ".result .MaxUsedCount | tonumber" ${LOG_DIR}/datasource.json` AverageBlockingTime=`/usr/local/bin/jq ".result .AverageBlockingTime | tonumber" ${LOG_DIR}/datasource.json` MaxWaitTime=`/usr/local/bin/jq ".result .MaxWaitTime | tonumber" ${LOG_DIR}/datasource.json` # GrowthForecastに送信する curl -F number=${InUseCount} ${GROWTH_FORCAST_ENDPOINT}/datasource/InUseCount 1>/dev/null 2>/dev/null curl -F number=${MaxUseCount} ${GROWTH_FORCAST_ENDPOINT}/datasource/MaxUsedCount 1>/dev/null 2>/dev/null curl -F number=${AverageBlockingTime} ${GROWTH_FORCAST_ENDPOINT}/datasource/AverageBlockingTime 1>/dev/null 2>/dev/null curl -F number=${MaxWaitTime} ${GROWTH_FORCAST_ENDPOINT}/datasource/MaxWaitTime 1>/dev/null 2>/dev/null
bashでは多少強引な感じがするので、HTTP-APIを持っていたり、jsonをパースするのが得意な言語で書くともっとスマートにできると思う。今後時間があるときにGroovy書き換えにトライしたい
4. 作成したスクリプトをcronに登録
先ほど作成したシェル(/home/test/monitor.sh)を、cronに登録する。今回は10秒間隔でデータを取得することにした。
# touch /etc/cron.d/jboss-monitoring # vim jboss-monitoring * * * * * test for i in `seq 0 10 59`; do (sleep ${i}; /home/test/tools/monitor.sh) & done;
まとめ
今回はJBossの管理HTTP-APIを使ってデータを収集し、GrowthForecastでグラフ化する方法を紹介した。例ではJBossとGrowthForecastが同じlocalhostで起動しているが、実際に長時間負荷試験などを行う場合は、別のマシンにそれぞれセットアップすることをお勧めする。
また、冒頭に書いたとおり、JBossの管理APIで取得できるのはデータソースの情報だけではなく、スレッドプールやトランザクションの状況などの様々な情報を収集できるので、同様の方法で色々なパラメータを監視することができる。ぜひテスト環境でもモニタリングを行って、運用し始めるまえに問題を検知して対処されることが広まると嬉しい。