Jshiike 3年弱前 edited | ▲upvoteする | link | parent | on: Java: 本番環境でのデバッグスキルを磨く

Takipi のFounderであるTalWeissのSan Francisco Java User Groupミートアップでの講演。本番環境で役に立つデバッグテクニックの紹介です。

1. スレッド名の活用

  • スレッド名はmutable(EJB除く)である。コードのコンテキストにあわせて、Thread.currentThread().setName(Context, TID, Params, Time,...);のようにすれば、トランザクションID、Serveletパラメータ、キューメッセージID、起動時間など、スタックトレースに役に立つ情報を表示できるようになる。
  • JConsole / Java Mission Control / プロファイラ / 有料サービスなどどのツールを利用していても、活用できる手法。
  • 更に上級バージョンとしては、スレッドのローカル変数を現在のスレッドに読み込み、ログappenderを設定し、各ログエントリーに自動的に付加されるようにする。
  • 複数のスレッドがサーバにログを書き込んでいて、その中の一つのスレッドに集中しなくてはいけないとき、分散 / SOA環境で実行しているときなどに、特に有効なアプローチ。

2. Uncaught handlers

  • Thread.UncaughtExceptionHandler が最後の防衛線になる。スレッドがクラッシュしたときに、スレッド名以外はどのようなステート変数も組み込まれていないことを担保する。
  • これがないと、いつどこにログされたのか、前後関係の不明なexceptionが発生するリスクがある。uncaught exception handler内でも、そのスレッド(すでにターミネートされている。)ではどの変数にもアクセスできないように見えるが、実際のスレッドオブジェクトの参照は取得できる。スレッド名をうまく工夫すれば、役に立つthread.getName()値をログできる。

3. Preemptive jstack

  • 本番環境でデバッグする際の基本ツールという位置付け。
  • 「ステート変数が取得できない」「過去を振り返るかたちでしか利用できない」という問題を解決する。
  • コードで何か悪いことが起きたら、jstackが起動する仕組み。サーバが落ちたり、アプリに設定した閾値を超えたり、スループットが想定より下がったり、デッドロックをアプリ内で検知したときなどをトリガーにできる。

4. Btrace

  • 上記3において、動的なステートを取得したいときに本番環境で使える便利なツール。稼働中のJVMに再起動せず、ステートを変更せずに利用できる。Javaエージェントとメタスクリプティング言語を使ってステートを取得。
  • 相当パワフルなので一番のオススメ。例えば、「特定のファイルに誰が書き込んでもスクリーンにプリントアウトする。」「誰がそのクラスを読み込んでいるか?どのスタックトレースが該当するか?」「誰かが新しいcharアレーをアロケートしてたら知らせて欲しい。」などに使える。
  • サンプルライブラリがとにかく豊富。
  • 制約事項(ビデオ 13分55秒時点のスライド)はかなりあるので事前に確認しておくこと。

5. Java Agents

  • コードを動的に操作できる。プロファイリング/デバッグツールの基本となる上級テクという位置付け。
  • 本番アプリからステートを取得できるパワフルツール。頼みたいことはほぼ何でもできる。JVMの再起動不要。
  • 二つのタイプのエージェント: Javaとnative
  • Javaエージェント
    • Javaで書かれていて、Instrumentation APIにアクセスする。
    • 自分で書いてものでなくても、サードパーティのコードでも操作できる。
    • バイトコードの知識が必要となる。
  • Nativeエージェント
    • JVMの最も深いところに関わりたいなら、JVMで起きていることのすべてを把握したいならこれがベスト。
    • C++で書かれていて、JVMTI(JVMのローレベルAPI群)にアクセスする。
    • 様々なコールバックを設定できる。例えば、「ガベージコレクションの開始と終了したとき」「モニタと同期したとき」「ブレークポイントをセットしてプログラム的に何が起きたか把握するためにポーズさせる」「アプリのどこの部分でも特定のフィールド値を誰かが変更したら」「どこかでexceptionを検知したら」「JITがメソッドをコンパイルしたら」など。
    • 書くのは複雑。プラットフォーム依存があり、mac/windowsではコンパイル手間がかかる。また、JVMレベルで操作するということは、JVMが守ってくれるというメリットを享受できなくなる。自分のミスがJVMを止めることに直結する。

6. The Serviceability API

  • (github.com/takipi/ServiceHeap というURLで紹介されているが見当たらず。。)
  • HSDB: JVMにアクセスして、再起動なしで、オブジェクトの特定のステート変数を個別に確認できる。
  • デモビデオ 31分30秒時点〜

参照: http://blog.takipi.com/5-techniques-to-improve-your-server-logging/


2014 Topアクセスランキング


Back