|
Arthasは、強力なオープンソースのJava診断プログラムです。簡単に起動でき、グラフィカルインターフェースでJavaプログラムを操作できます。プログラムのメモリ使用量、スレッド情報、GCステータスの監視をサポートし、既存のコードを逆コンパイルして変更することも可能です。 下の図に示すように、Arthas の動作原理は一般的に次の手順で構成されます。
読者が Arthas の基本を素早く学習して習得できるように、この記事では、よく遭遇するいくつかの例を使用して、Arthas の日常的な使用方法の一般的な例を示します。 Arthasの設定と使用方法の詳細な説明クイックスタートいくつかの典型的な事例を紹介する前に、Arthasをダウンロードして基本的な使い方を学ぶ必要があります(注:デモ環境はWindows 10に基づいていますが、Linuxでも操作は同様です)。Arthasの公式サイトは以下の通りです。 https://arthas.aliyun.com/ 便宜上、私は通常、ダウンロードにコマンドラインを使用します。 完了したら、次のコマンドを使用して Arthas を起動できます。 インターフェースに初めてアクセスするとわかるように、Arthasはサーバー上で実行されている各Javaプログラムに番号を付けます。対応する番号を入力してEnterキーを押すだけで、対象プログラムを監視できます。デモのために、ランダムに2を選択してEnterキーを押しました。 次に、下の画像に示すように、インタラクティブ インターフェイスに入りました。 Arthasで最もよく使われる監視コマンドはdashboardです。dashboardの使い方を説明するには、Linuxと同様にdashboardコマンドに--helpを追加します。 下の画像に示すように、ダッシュボードは通常次のように使用されます。
したがって、10 秒ごとに更新する場合、3 回実行されるコマンドは次のようになります。 パネルは10秒ごとに更新されます。監視インターフェースは以下の画像に示されています。この画像から、ダッシュボードがおおまかに3つのセクションで構成されていることがわかります。
Arthas では、ダッシュボードを終了するには Ctrl+C を押すだけです。現在の Java プログラムの対話型インターフェースを終了するには、「exit」と入力します。 CPU 100% 問題の場所を特定するCPU 100% 問題は、本番環境におけるトラブルシューティングが最も難しい問題の一つです。Arthas 導入前は、一般的なトラブルシューティングのアプローチはおおよそ次のとおりでした。
上で述べたように、かなり面倒ではないでしょうか?Arthasを使えば、問題の特定がはるかに簡単かつ迅速になります。この例を説明するために、Spring Bootプロジェクトを使ってCPU使用率100%の問題をシミュレートするコードスニペットを作成しました。以下のコードを使用していることがわかります。 コードが完成したら、プロジェクトを起動してアドレスをリクエストします。するとすぐにCPU使用率が100%近くまで急上昇することがわかります。ここでArthasが役立ちます。当然ですが、まずArthasを起動します。 この時点で、コンソールには以下のオプションが表示されます。各オプションは異なるJavaプログラムを示すために異なる番号で識別されます。ターゲットプログラムであるArthasExampleApplicationの番号は1なので、1を入力してEnterキーを押します。 コンソールに入り、thread コマンドを直接入力すると、CPU 使用率が非常に高い pool-1-thread-1 という名前のスレッドがあることがわかります。そのため、このスレッドが動作しているコード セグメントを見つける必要があります。 コンソールからわかるように、シリアル番号は 59 なので、次のように直接入力できます。 問題のあるコード セグメントは TestController の 42 行目にすぐに見つかりました。 コードの場所を特定したら、クラスのパッケージパス(com.example.arthasExample.TestController)に基づいてArthasを使用して直接逆コンパイルし、ソースコードを表示できます。コマンドは以下のとおりです。 最終的に問題のあるコードが見つかり、すぐに修正されました。 スレッドデッドロックの問題の特定スレッドデッドロック問題に関して、以下のサンプルコードも提供しています。スレッド1はまずロック1を取得し、次にロック2を取得しますが、スレッド2はその逆を行います。この2つのロック取得順序がループを形成し、デッドロックが発生します。 コードフローを理解した後、このインターフェースを直接呼び出します。Arthasを開き、「thread」と入力してスレッド情報を表示します。2つのスレッド(t1とt2)が待機状態になっていることがわかります。これはおそらく問題が発生していることを示しています。 次に「thread -b」と入力すると、スレッド t2 がロックされていることがわかり、2 つのスレッド間にデッドロックが存在することが判明しました。 上記の結果から、2つのスレッドのIDはそれぞれ65と66であることがわかります。したがって、スレッドID番号を指定したコマンドを使用することで、問題のあるコードセグメントを直接特定し、問題を解決できます。 コードを逆コンパイルして表示する上記で既にjad逆コンパイルコマンドを使用しました。私にとって、jadには2つの一般的な用途があります。クラスを逆コンパイルするコマンド(jad --source-only class_package_path)に加えて、メソッドのコードセグメントを検索するコマンド(jad --source-only class_package_path_method_name)もあります。 たとえば、TestController 内の deadLock コードを見つけたい場合は、次のように入力します。 下の画像に示すように、メソッドのコードを直接確認できます。 場所フィールド情報(あまり使用されない)特定のクラスの下にあるすべてのフィールドの詳細を表示する場合は、このコマンドを使用できます。 たとえば、TestController のフィールドの詳細を表示する場合は、次のコマンドを入力します。 ご覧のとおり、このコマンドを使用すると、フィールドの定義と注釈だけでなく、スレッド プールの使用状況とコレクション内の値も表示できます。 メソッドのリストを表示する(あまり使用されない)このコマンドはあまり使いませんが、完全性のために説明しておきます。クラスのメソッドを表示したい場合は、次のようにします。 私自身を例にとると、TestController を表示する方法は次のとおりです。 出力は次のようになります。 静的変数モニタリング(一般的に使用される)Arthasは静的変数の解析機能を提供します。例えば、次のコードスニペットでは、リスト内の詳細を確認したい場合はognlを使用できます。 API呼び出しを完了し、アイテムを追加したら、OGNLを使って直接監視できます。例えば、上記のリストの内容を確認したい場合は、次のコマンドを使用します。 したがって、リストを表示したい場合、コマンドは次のようになります。 出力は次のようになります。 もちろん、OGNLには、コレクションの長さのチェックやコレクションへの要素の追加など、より特殊な用途もあります。詳細については、こちらのGitHubのissueをご覧ください。 https://github.com/alibaba/arthas/issues/71 実行時パフォーマンスの問題のトラブルシューティング操作の実行時間はログ記録によって監視されることがよくあります。しかし、複雑な本番環境では、考慮不足のために特定のメソッドの監視を忘れてしまうことがよくあります。Arthasは同様に、メソッドの実行時間を監視および計算するための便利なコマンドを提供しています。 ここでは、ユーザー クエリ中にパラメータ検証、他のサービス、Redis、および MySQL への呼び出しをシミュレートする UserServiceImpl の例を示しました。 対応するコントローラーコードは以下の通りです。本番環境でこのインターフェースが非常に時間がかかり、ログも取得できない場合、Arthasを使用してどのようにトラブルシューティングすればよいでしょうか? `trace` コマンドを使うことができます。まずは `TestController` 内の `queryUser` への時間のかかる呼び出しを `trace` を使ってトレースしてみましょう。 TestController には例外がなく、常に UserServiceImpl で消費が発生していることがわかります。 したがって、UserServiceImpl の queryUser に対してコールバックを実行します。 コマンドを入力すると、コンソールはこのメソッドをブロックして監視します。その後、このインターフェースを呼び出すと、MySQLクエリに非常に時間がかかることがわかります。これにより、問題をさらに推測することができます。 メソッド時間消費統計特定の時間単位内でのメソッドのリクエスト時間と呼び出しステータスを監視したい場合があります。`monitor` コマンドを使用できます。例えば、`TestController` の `queryUser` ステータスを5秒ごとに確認したい場合は、次のように入力します。 コンソールには、リクエストの数、成功と失敗の数、5 秒ごとの平均所要時間などの情報が表示されます。 入力/出力パラメータエラーの特定ログが欠落しているメソッド(上記の mysql() の入出力パラメータなど)の入出力パラメータの詳細を特定したい場合があります。Arthas の watch メソッドと以下のコマンドを使用することで、これを実現できます。 ご覧のとおり、入力パラメータは 1 で、出力パラメータはオブジェクトです。 さらに、オブジェクトの内容を印刷したい場合は、toString メソッドを使用できます。 これらの機能に加えて、ウォッチは他の多くの高度な機能をサポートしています。詳細については、公式ドキュメントを参照してください: https://arthas.aliyun.com/doc/watch.html メソッド呼び出しパスの監視上記の MySQL メソッドを例にとると、その呼び出しパスをすばやく見つけたい場合は、stack メソッドを使用できます。 詳細な呼び出しパスを確認し、コンソールに直接出力することができます。 メソッド呼び出しを取得するプロセスメソッド呼び出し中に例外が発生した理由を確認し、入力パラメータと出力パラメータを調べるには、`tt` コマンドを使用します。例えば、`check` メソッドがエラーをスローする理由を確認したい場合は、`tt` を使用します。 出力から判断すると、例外が2回目にスローされたようです。インデックス1001を使って問題箇所を特定できます。 最終的に、入力パラメータは -1 であると結論付けることができます。 通話を再開したい場合は、以下を使用できます。 OOM問題以下のコードを例に、コマンド -Xms100m -Xmx100m を使用してヒープ メモリを 100m に変更したところ、起動直後に OOM の問題が再現されました。 その後、Arthas を使用してみると、旧世代のメモリがほぼいっぱいになっており、ガベージ コレクションが非常に頻繁に行われていることがわかりました。 したがって、Arthas の heapdump 関数を直接使用して、ファイルを .mat ファイルにエクスポートし、さらに分析することができます。 エクスポートされた結果は以下に表示されます。「詳細」をクリックすると、問題の原因を推測できます。 問題のあるコードはすぐに見つかりました。 オンラインコード置換テスト中に、どうしても見落としてしまうケースがあります。例えば、以下に示すように、ビジネス要件では id が 1 未満の場合にのみ例外をスローする必要があります。しかし、不注意により、条件を id<2 と記述してしまいました。その結果、このコードを知らずに本番環境にデプロイしてしまい、ビジネスクエリで問題が発生してしまいました。 本番環境では、JARファイルをすぐに再起動して置き換えることはできません。このような問題には、Arthasを使用してオンラインホットアップデートを実現できます。 まず、以下に示すように、本番環境からバイトコードを逆コンパイルし、ローカル マシンにエクスポートします。 次に、対応するコード スニペットを変更します。 次に、このクラスに対応するクラスローダーのハッシュコードを見つける必要があります。 対応するハッシュ コードが見つかったら、このクラス ローダーを使用して、変更された Java ファイルをバイトコードにコンパイルできます。 最後に、実行中のプログラムにコードをホットアップデートします。 ここで、パラメータとして 1 を渡すと、エラーは発生せず、コードのホット アップデートが成功したことが示されます。 さらに分析するために Spring コンテキストを取得します。Springコンテナの解析情報を取得し、オンラインで問題箇所を特定したい場合があります。Arthasを介してこのクラスをインターセプトし、さらに呼び出して解析を行うことができます。 Spring MVCのソースコードに詳しい読者の方は、HTTPリクエストがWebコンテナに送信されるたびに、マッピングおよび転送プロセス中にRequestMappingHandlerAdapterを経由することをご存知でしょう。下のクラス図からわかるように、このクラスはWebApplicationObjectSupportを継承しており、getWebApplicationContextメソッドによってSpringコンテナのコンテキストを取得し、Springコンテナを分析・管理することができます。 したがって、Arthas の tt 命令を使用して、このクラスへの呼び出しをトレースできます。 次に、任意の API を呼び出して呼び出しログを取得します。 インデックス 1000 の呼び出しレコードを使用し、-w で OGNL を指定して Spring コンテキストと testController を取得し、メソッド呼び出しを完了します。 下の画像に示すように、呼び出しが正常に完了し、返された結果を受け取ったことがわかります。 まとめArthasの一般的な操作のデモはこれで終了です。Arthasの使い方の詳細については、Arthasの公式ウェブサイト(https://arthas.aliyun.com/doc/)をご覧ください。 |