午前2時のアラートと、ログを「手探り」で調査した夜
Javaのマイクロサービス群を運用し始めたばかりの頃、私が最も恐れていたのは深夜に届くシステムダウンの通知でした。当時は、まずサーバーにSSHで入り、top -Hやjstat、jstackをがむしゃらに入力して原因を突き止めようとしていました。その感覚は、懐中電灯なしで暗闇の中で車を修理しているようなもので、非常に受動的で疲弊する作業でした。
Prometheus JMX Exporter、Prometheus、Grafanaの「三種の神器」を導入してからは、状況が一変しました。アプリが落ちるのを待つのではなく、ダッシュボードを見るだけでトラブルの兆候を察知できるようになったのです。この記事では、Javaアプリのための本格的な監視システムを構築するための実践的な経験を凝縮して紹介します。
JMX Exporter:JVMのための「通訳者」
すべてのJava仮想マシン(JVM)には、リソース管理のためのJMXが標準で備わっています。しかし、Prometheusはフォーマットが異なるため、このデータを直接読み取ることができません。JMX Exporterはjavaagentとして動作し、アプリケーションと並行して実行されることで、メトリクスをPrometheusが理解できるHTTP/テキスト形式に変換する役割を果たします。
なぜ独立したサービスではなくエージェント形式を選ぶのでしょうか? 多くのプロジェクトを通じて、エージェント形式の方が圧倒的に安定していることが分かりました。アプリと一緒に起動するため、外部プロセスの管理が不要になり、データ取得の遅延も最小限に抑えられます。
Các bước triển khai thực tế
ステップ1:JMX Exporterエージェントのダウンロード
アプリに組み込むためのエージェントのJARファイルが必要です。Maven CentralやGitHubから最新バージョン(例:0.20.0)をダウンロードしてください。ファイルサイズは数MB程度と非常に軽量です。
mkdir -p /opt/monitoring
cd /opt/monitoring
wget https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.20.0/jmx_prometheus_javaagent-0.20.0.jar
ステップ2:スマートなconfig.yamlの設定
メトリクスをフィルタリングしないと、JMXは何千もの不要なパラメータを出力し、Prometheusに負荷をかけてしまいます。以下は、CPU、スレッド、GCなどの最も重要な指標に焦点を当てるために私がよく使用しているフィルタ設定です:
# /opt/monitoring/config.yaml
startDelaySeconds: 0
ssl: false
lowercaseOutputName: true
rules:
- pattern: 'java.lang<type=OperatingSystem><>((?!processCpuTime)\w+):'
name: os_$1
type: GAUGE
- pattern: 'java.lang<type=Threading><>ThreadCount:'
name: jvm_threads_current
type: GAUGE
- pattern: 'java.lang<type=Memory><>HeapMemoryUsage:(.*):'
name: jvm_memory_heap_$1
type: GAUGE
- pattern: 'java.lang<type=GarbageCollector, name=(.*)><>CollectionCount:'
name: jvm_gc_collection_count
labels:
gc: "$1"
type: COUNTER
ステップ3:アプリケーションへのエージェントの適用
起動コマンドに-javaagentパラメータを1行追加するだけです。ポート番号(例:8080)は、Webアプリのメインポートと重複しないように注意してください。
java -javaagent:/opt/monitoring/jmx_prometheus_javaagent-0.20.0.jar=8080:/opt/monitoring/config.yaml \
-jar your-app.jar
実行後、http://<サーバーのIP>:8080/metricsにアクセスしてみてください。jvm_memory_heap_usedのようなテキスト行が表示されれば成功です。
ステップ4:PrometheusおよびGrafanaとの連携
prometheus.ymlファイルに、Prometheusが定期的にデータを取得(scrape)するためのジョブを追加します。リアルタイム監視には、scrape_intervalを15秒程度に設定するのが丁度良いでしょう。
scrape_configs:
- job_name: 'java-microservice'
static_configs:
- targets: ['192.168.1.10:8080']
最後に、GrafanaでダッシュボードID 8563をインポートします。自分でチャートを作成する手間をかけずに、プロフェッショナルな監視画面をすぐに手に入れることができます。
厳重に監視すべき3つの「死活」指標
あまりに多くのグラフに圧倒されないでください troubleshootingの経験に基づくと、以下の3つの領域に集中するだけで十分です:
- Heap Memory Usage: グラフがのこぎり状になっていても、底値が徐々に上がっている場合は、メモリリークの可能性が高いです。Heapが85%を超えたらアラートを出すように設定しましょう。
- GC Stop-The-World:
jvm_gc_collection_seconds_sumが急増すると、アプリがフリーズします。200msを超えるGCが発生すると、ユーザーはアプリのラグをはっきりと感じるようになります。 - Thread Count: スレッド数が継続的に増加している場合は、デッドロックやデータベース接続プールの枯渇が原因であることが多いです。
まとめ
監視は単に綺麗なグラフを眺めるためのものではありません。受動的な対応から能動的な管理へと切り替えるための手段です。「サーバーが重い気がします」と言う代わりに、「モジュールXのメモリリークにより、Heapが90%に達しています」と自信を持って報告できるようになります。信頼できる監視システムを構築して、ぐっすり眠れる夜を手に入れましょう!

