どうも、cloudpack のかっぱ (@inokara) です。
はじめに
JVM のヒープメモリを sensu で監視するにあたって Jolokia 経由での監視を考えていたのですが、既に java-permgen.rb というプラグインがあったのでそちらを試してみました。
参考
memo
java-permgen.rb の仕組み
ソースコードをざっくり見てみると jps
で JVM の PID を取得して、取得した PID を利用して jstat
を実行しているようです。また、jstat
を実行して PGCMX
と PU
という二つの値を取得して割り算して Permanent
領域の使用率をチェックしているようです。
上記のようなフローになりますでしょうか…
jps について
jps とはJava 仮想マシンプロセスステータスツール
とあります。
上記のドキュメントをもう少し読むと以下のように書かれています。
jps ツールは、ターゲットシステム上で計測された HotSpot Java 仮想マシン (JVM) を一覧表示します。このツールで表示できるレポート情報は、アクセス権を持った JVM に関するものに限定されます。
hostid を指定せずに jps を実行した場合、ローカルホストで計測された JVM が検索されます。hostid を指定して起動した場合、指定されたプロトコルとポートを使用して、指定されたホスト上の JVM を検索します。jstatd プロセスがターゲットホスト上で実行されていると想定されます。
ps
コマンドのように実行中の JVM プロセス(ローカル VM 識別子)ID を出力してくれるようです。
試しに Play Framework が動作している環境で root
権限にて jps
を実行してみます。
$ sudo su - Last login: Tue Nov 18 10:41:32 UTC 2014 on pts/0 # jps 2294 NettyServer 2752 Jps
上記のように JVM の ID と共に実行しているアプリケーション名(クラス名、JAR ファイル名等)が出力されました。アプリケーション名の出力を抑制するオプション(-q
)もあるようです。
jstat について
jstat とは Java 仮想マシン統計データ監視ツール
とあります。
上記のドキュメントを読むと jstat
は以下のように書かれています。
jstat ツールは、設置されている HotSpot Java 仮想マシン (JVM) のパフォーマンス統計データを表示します。ターゲット JVM は、仮想マシン識別子、つまり下記の vmid オプションによって識別されます。
jstat
は以下のように実行します。
jstat ${jps で出力された ID}
さらに jstat
には多くの出力オプションがあり、今回の java-permgem.rb プラグインでは以下のオプションがプラグイン内部で実行されています。
-gcold オプション
Old および Permanent 世代の統計データを出力します。-gcold
オプション付きで実行すると以下のように出力されます。
# jstat -gcold ${ID} PC PU OC OU YGC FGC FGCT GCT 21248.0 20028.7 699072.0 0.0 0 0 0.000 0.000
各項目は以下の通りです。(ドキュメントより抜粋)
項目 | 説明 |
---|---|
PC | Permanent 領域の現在の容量 (KB) |
PU | Permanent 領域の使用容量 (KB)※ドキュメントでは「使用率」とありますが「使用容量」と修正しました |
OC | Old 領域(Tenured Generation 又は Old Generation)の現在の容量 (KB) |
OU | Old 領域(Tenured Generation 又は Old Generation)の使用率 (KB) |
YGC | 若い世代(Young Generation)の GC イベント数 |
FGC | フル GC イベント数 |
FGCT | フルガベージコレクション時間 |
GCT | ガベージコレクション総時間 |
-gcpermcapacity オプション
Permanent 世代の統計データを出力します。-gcpermcapacity
オプション付きで実行すると以下のように出力されます。
# jstat -gcpermcapacity ${ID} PGCMN PGCMX PGC PC YGC FGC FGCT GCT 21248.0 262144.0 21248.0 21248.0 0 0 0.000 0.000
各項目は以下の通りです。(ドキュメントより抜粋)
項目 | 説明 |
---|---|
PGCMN | Permanent 世代の最小容量 (KB) |
PGCMX | Permanent 世代の最大容量 (KB) |
PGC | Permanent 世代の現在の容量 (KB) |
PC | Permanent 領域の現在の容量 (KB) |
YGC | 若い世代の GC イベント数 |
FGC | フル GC イベント数 |
FGCT | フルガベージコレクション時間 |
GCT | ガベージコレクション総時間 |
Java オブジェクトのメモリ領域
上記の Old 領域や Permanent 世代とかなんぞやって思っていたら、こちらの資料に辿り着いたので整理してみました。
領域 | 説明 |
---|---|
New(Young Generaion)領域:ヒープ領域 | New 領域は Eden と From と To の領域に分かれる。この領域が不足すると Scavenge GC が頻発する。 |
Old(Tenured Generation 又は Old Generation)領域:ヒープ領域 | New 領域で破棄されなかったオブジェクトが配置される。この領域が不足すると Full GC が行われる。 |
Permanent 領域:非ヒープ領域 | クラス、メソッドの情報が格納される。この領域が不足すると Full GC が行われる。 |
ふむふむ…あくまでもドキュメントの写経ですのでもっと JVM の勉強をする必要がありそうです…orz
Demo
準備
とりあえず sensu-plugin を入れておきましょう。
sudo gem install sensu-plugin --no-ri --no-rdoc -V
試す
root 権限で実行しましょう。
sudo su - cd sensu-community-plugins/plugins/java
以下のように実行します。
# ./java-permgen.rb -w 1 -c 2 Java PermGen CRITICAL: Java processes Over PermGen CRIT threshold of 2%:
Critical を発生させる為に閾値を極端に低くしていますが、Critical を検出した JVM の ID(2294
)も一緒に出力されています。
ちょっとデバッグ
PU
と PGCMX
を出力させてみました。
# ./java-permgen.rb -w 1 -c 2 "pgcmx: " "pgcmx: 262144.0" "pu: 20028.7" Java PermGen CRITICAL: Java processes Over PermGen CRIT threshold of 2%: 2294 # jstat -gcpermcapacity 2294 PGCMN PGCMX PGC PC YGC FGC FGCT GCT 21248.0 262144.0 21248.0 21248.0 0 0 0.000 0.000 # jstat -gcold 2294 PC PU OC OU YGC FGC FGCT GCT 21248.0 20028.7 699072.0 0.0 0 0 0.000 0.000
上記のように PU
と PGCMX
の値が取得されていることが分かります。
それでは…
学んだこと
- JVM のプロセス ID を取得する場合には
jps
を利用する jstatで
JVM のヒープ領域等の各種リソースを取得可能(オプションは多数あり取得出来る項目が異なる- java-permgen.rb プラグインは
jstat
の異なるオプションから取得する値を算出してチェックを行う
次はどんなプラグインに出会うんでしょうか
次はどんなプラグインに出会うんでしょうか。
非常に楽しみですね。
さよなら、さよなら。
元記事はこちらです。
「Sensu Community Plugin 探訪(2)java-permgen.rb を試した」