DUICUO

Arthasの簡潔な設定と基本的な操作およびメンテナンスのチュートリアル

Arthasは、強力なオープンソースのJava診断プログラムです。簡単に起動でき、グラフィカルインターフェースでJavaプログラムを操作できます。プログラムのメモリ使用量、スレッド情報、GCステータスの監視をサポートし、既存のコードを逆コンパイルして変更することも可能です。

I. Arthasの動作原理を簡単に説明する(理解)

Arthas の基本的な動作原理は次のとおりです。

  • Arthas を起動し、対象の Java プログラムを選択すると、Arthas は対象プログラムにプロキシを挿入します。
  • プロキシは、HTTP と Telnet を組み合わせてクライアントとの接続を確立するサーバーを作成します。
  • クライアントはサーバーとの接続を確立します。
  • その後のクライアント側の監視やプログラムの調整は、サーバー側の Java インストルメンテーション メカニズムを通じてアプリケーションと対話することで実行できます。

II. Arthasの基本的な使用方法の詳細な説明

1.ダウンロードしてインストールする

いくつかの典型的な事例を紹介する前に、Arthasをダウンロードしてインストールする必要があります。Arthasの公式サイトは以下の通りです。

Arthasの公式サイト:https://arthas.aliyun.com/

便宜上、私は通常、ダウンロードにコマンドラインを使用します。

 curl -O https://arthas.aliyun.com/arthas-boot.jar

完了したら、次のコマンドを使用して Arthas を起動できます。

 java -jar arthas-boot.jar

この時点で、対応するプロセスIDとプロセスPIDを確認できます。例えば、Arthasを起動すると、シリアル番号1(9121)のJavaプロセスが表示されます。1を直接クリックしてEnterキーを押すと、このプロセスを監視および管理できます。

 [INFO] JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64/jre [INFO] arthas-boot version: 3.7.2 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. * [1]: 9121 arthasExample.jar

Arthas は最初の試行で必要な依存関係をダウンロードします。その後、Arthas を正式に使用して現在のプロセスを管理できるようになります。

2. オフラインユーザー向けアプリの使い方(オプション)

イントラネット上のユーザーはインターネットに接続できず、Arthasを初期化できないため、Arthasではフルパッケージをダウンロードできる便利なオプションも提供しています。必要な方はダウンロードページにアクセスし、フルパッケージのダウンロードを選択して、Arthasの完全なパッケージを入手できます。

ダウンロードして解凍したら、次のスクリプト コマンドを使用して Arthas をすぐに起動できます。

 ./as.sh

3. 一般的なコマンドの紹介

Arthasに入ると、いくつかの基本的な操作を実行できます。以下はLinuxに似た、私がよく使うコマンドです。読者の皆様は、さらに詳しい情報を得るためにこれらのコマンドを参照してください。

  • cat: ファイルの内容を出力します。
  • cls: 現在の画面領域の内容をクリアします。
  • grep: 一致する検索。
  • history: コマンド履歴を出力します。
  • pwd: Java プロセスの現在の場所を入力します。
  • quit: 現在の Arthas クライアントを終了します。
  • `stop`: Arthas サーバーをシャットダウンします。すべての Arthas クライアントが終了します。

ここで簡単なデモンストレーションを行います。pwdの出力は、監視対象のJavaプロセスが配置されているファイルディレクトリであることがわかります。

 [arthas@9121]$ pwd # 当前监控的进程在服务器上的目录/home/sharkchili/arthasExample [arthas@9121]$

たとえば、ヒープメモリの使用量を確認するときに、古い世代のデータのみを表示する場合は、grep を使用できます。

 memory |grep ps_old_gen

「終了」をクリックすると、現在のクライアントプロセスが直接終了します。「停止」も同様の動作をしますが、通常はクライアントだけでなく、サーバーと他のクライアントも強制終了します。ここではその説明は省略します。

 [arthas@9121]$ quit # 直接返回到服务器的目录sharkchili@DESKTOP-7IPKPVJ:~/arthas$

4. クイックスタート設定

Arthasを素早く起動するための、私独自の設定方法もご紹介します。まず、arthas-boot.jarの起動手順を含むas.shというスクリプトをvimで編集します。

 java -jar /home/sharkchili/arthas/arthas-boot.jar

スクリプトを完了し、起動が成功したことを確認したら、次の内容を含むエイリアスを使用してこのスクリプトを /etc/profile に追加します: sh コマンドの後にスクリプトのフルパスが続きます。

 alias as="sh /home/sharkchili/arthas/as.sh"

次に、ソース ディレクティブを使用してこれを有効にします。

ご覧のとおり、この設定を完了すると、`as` コマンドを直接使用して Arthas をすばやく起動できます。

 # 键入as sharkchili@DESKTOP-xxx:~$ as # 直接快速启动arthas [INFO] JAVA_HOME: /usr/lib/jvm/java-8-openjdk-amd64/jre [INFO] arthas-boot version: 3.7.2 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. * [1]: 9121 arthasExample.jar

III. Arthasでよく使われる操作・メンテナンスコマンド

1. リアルタイムデータパネルを表示する

日々の開発・保守プロセスにおいて、プロジェクトの検査は非常に重要です。Arthasのダッシュボードは、現在のシステムにおけるプロセスの実行状況を非常に直感的に把握できます。

Arthasのコントロールパネルで「ダッシュボード」と入力してください。デフォルトでは5秒ごとに更新されます。

ここでは、最初のセクション「スレッド」のフィールドの意味について簡単に説明します。

  • ID: Java レベルのスレッド ID。jstack のネイティブ ID との違いに注意してください。
  • NAME: スレッド名。
  • GROUP: スレッドが属するスレッド グループの名前。
  • PRIORITY: スレッドの優先度。値が高いほど優先度が高くなります。
  • STATE: スレッドの実行ステータス。
  • CPU%: スレッドの CPU 使用率。
  • DELTA_TIME: 最後のサンプリング以降のスレッド実行の CPU 時間 (秒)。
  • TIME: スレッドの実行にかかる CPU 時間の合計 (分:秒形式)。
  • INTERRUPTED: スレッドの現在の割り込みステータス。
  • DAEMON: デーモン スレッドであるかどうか。

2番目のセクションはメモリ使用量セクションで、各ヒープ領域とメタスペースのメモリ使用量とGC情報が記録されます。3番目のセクションはサーバーランタイムパラメータセクションで、プログラムが現在実行されているサーバーのカーネルバージョンやJDKバージョンなどの情報が記録されます。

Arthasのコマンドラインインターフェースは`--help`オプションでアクセスできることを知っておくことが重要です。ダッシュボードを例にとると、使用方法は次のとおりです。`-i`オプションはダッシュボードの更新間隔(ミリ秒単位)を指定し、`-n`オプションは更新回数を指定します。

したがって、1 秒ごとに 1 回更新し、5 回更新する場合、対応するコマンドは次のようになります。

 dashboard -i 1000 -n 5

2. JVM情報を表示する

Arthas は JVM 情報の非常に直感的なビューも提供し、対応するコマンドも JVM に関連しています。

このコマンドも複数のセクションを出力します。最初のセクションを見てみましょう。ご覧のとおり、このコマンドはマシン名、JVMの起動時間、JDKのバージョン、そして設定されたJVMパラメータを明確に表示しています。

セクションはたくさんあるので、ここでは私がよく使う「スレッド」セクションと「ファイルディスクリプタ」セクションだけを紹介します。この2つのセクションを通して、スレッドのデッドロックが発生していないか、リソースが適切なタイミングで閉じられていないかなど、定期的なチェックを行うことができます。

  • THREAD: 現在アクティブなスレッドの数、アクティブなデーモン スレッドの数、JVM の起動以降に実行されたスレッドの最大数、開始されたスレッドの合計数、および終了したスレッドの数を記録します。
  • FILE-DESCRIPTOR: このセクションには、JVM が開くことができるファイル記述子の最大数と現在開いているファイル記述子の数を記録します。

3. ログの表示と変更

`logger`コマンドは私のお気に入りの一つです。ログ設定を非常に直感的に表示してくれます。下の画像のように、現在実行中のプログラムを例にすると、次のような情報が表示されます。

  • ログ レベルは INFO です。
  • エラー ログが保存される ERROR_FILE ファイルへの相対パス。
  • 通常のログ ファイルを保存するために使用される INFO_FILE ファイルへの相対パス。

もちろん、特定の名前のログ情報を表示することもできます。例えば、com.example.arthasExample.TestControllerのログ情報を表示したい場合は、コマンド「logger -n com.example.arthasExample.TestController」を直接入力します。

loggerコマンドには、ログレベルを直接変更するという便利な機能もあります。例えば、ROOTというファイルのログレベルを変更したい場合は、以下の手順で変更できます。

  • classLoader のハッシュ コードを取得します。
  • ログ レベルは、ハッシュ コードに基づいて logger コマンドを使用して変更できます。

プログラムには次のコード スニペットが含まれており、次の API を要求すると、情報レベルのログのみが出力されます。

 @GetMapping(value = {"/user/logger"}) public String loggerPrint() { log.info("info logger"); log.debug("debug logger"); return "success"; }

対応する出力は次のようになります。

 2024-08-19 23:53:29.454 INFO ceaTestController :138 http-nio-8080-exec-1 info logger

次に、Arthasを使ってログレベルを直接変更します。まず、現在のクラスローダーのハッシュコードを取得する必要があります。

 sc -d com.example.arthasExample.TestController

次に、このハッシュ コードを直接使用して次のコマンドを実行し、ログをデバッグに設定します。

 logger -c 306a30c7 --name ROOT --level debug

デバッグ ログが表示されました:

 2024-08-20 00:13:31.438 INFO ceaTestController :138 http-nio-8080-exec-6 info logger 2024-08-20 00:13:31.439 DEBUG ceaTestController :139 http-nio-8080-exec-6 debug logger

4. JVMメモリ情報を表示する

次は、私がよく使うコマンドの一つである「memory」コマンドです。「memory」を使うと、現在のメモリ使用量を監視できます。下の画像のように、「memory」コマンドを入力すると、使用メモリ、合計サイズ、最大値、各領域の使用率などの情報を確認できます。

同様に、上記の「メモリ」セクションでは各行の意味も示します。

  • heap: ヒープメモリ領域。
  • ps_eden_space: ヒープメモリ内の Eden スペース。若い世代を表します。
  • ps_survivor_space: ヒープメモリ内の若い世代の Survivor スペース。
  • ps_old_gen: ヒープメモリの古い世代。
  • nonheap: ヒープメモリ外のメモリである非ヒープメモリ。
  • code_cache: Java 実行ではバイトコードがマシン コードにコンパイルされるため、この領域はコードのこの部分をキャッシュするために使用されます。
  • メタスペース: JDK 1.8 を例にとると、このスペースは Java クラスとメソッド、定数プールなどのメタデータ情報を格納するために使用されます。
  • compress_class_space: クラス ファイル情報が格納される領域。

ここでは、JVMメモリ領域の配分について簡単に説明します。メモリ命令の各フィールドの意味を理解するために、次の図を参照してください。

5. JVM環境変数を確認する

Arthasの`sysenv`コマンドは、システム環境変数の情報を取得するためによく使用されます。このコマンドを入力すると、以下の画像に示すように、現在のJavaプログラムで使用されているほとんどのシステム環境変数を確認できます。現在のシステムユーザー名、エンコード形式、現在のプログラムパス、クライアントIPアドレス、ポート番号などの情報が表示されます。

ヘルプ ドキュメントによると、このコマンドは個々の環境変数の照会もサポートしていますが、誰もが環境変数の名前を知っているわけではないので、あまり役に立ちません。調べて見つけなければなりません (笑)。

 [arthas@23543]$ sysenv PWD KEY VALUE ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ PWD /home/sharkchili/arthasExample

6. JVMシステムプロパティの表示と変更

`sysprop` コマンドは、JVM のシステムプロパティを表示します。基本的に、このコマンドを使用すると、JVM のパラメータ設定情報のほとんどを表示できます。以下の出力には、JDK のバージョン、プログラム名、ログのエンコード形式、現在のシステムユーザー名などが表示されています。

7. 現在のJVMスレッドスタック情報を表示する

Arthasは、以下に示すように、スレッド情報を表示するための`thread`コマンドを提供しています。このコマンドは基本的に、スレッド数情報と複数のアクティブスレッドのリアルタイム情報を出力します。デフォルトでは、データはCPUインクリメント時間の降順でソートされます。

ヘルプドキュメントで提案されているように、-n オプションを使用して、最初の数個のビジースレッドのコールスタック情報を出力することも可能です。以下に示すように、最初の2つのビジースレッドを出力するには、`thread -n 2` コマンドを入力します。

Arthasは時間間隔での出力もサポートしています。例えば、5秒以内の最もビジーなスレッドを3つ一覧表示したい場合、対応するコマンドは以下のようになります。

 thread -n 3 -i 5000

Javaプログラムに多数のスレッドがあり、特定の状態のスレッドをフィルタリングしたい場合は、`--state` オプションを使用して指定できます。例えば、RUNNABLE状態のスレッドを出力したい場合は、`thread --state RUNNABLE` と入力して出力を取得できます。

デッドロックの問題に関しては、以下の図に示すように、-b コマンドを使用して、現在のプログラム内で他のスレッドをブロックしているスレッドがあるかどうかを特定し、確認することもできます。著者の例では、現在のプログラムにはデッドロックは発生していません。

この時点で、デッドロックをトリガーして呼び出すためのインターフェースを提供します。

 @RequestMapping("dead-lock") public void deadLock() { //线程1先取得锁1,休眠后取锁2 new Thread(() -> { synchronized (lock1) { try { log.info("t1 successfully acquired the lock1......"); TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock2) { log.info("t1 successfully acquired the lock1......"); } } }, "t1").start(); //线程2先取得锁2,休眠后取锁1 new Thread(() -> { synchronized (lock2) { try { log.info("t2 successfully acquired the lock2......"); TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lock1) { log.info("t2 successfully acquired the lock1......"); } } }, "t2").start(); }

この時点で、-b コマンドを入力すると、他のスレッドをブロックしているスレッドと、そのスレッドが含まれているコード セグメントが見つかります。

8. vmtoolによるJVMの制御

vmtool は私が頻繁に使用するツールコマンドです。オブジェクトのクエリやガベージコレクションの強制実行などに使用できます。これらの機能の詳細については、公式ウェブサイトをご覧ください。

vmtool:https://arthas.aliyun.com/doc/vmtool.html

ここで紹介したいのは、スレッドを強制的に中断する機能です。このコマンドは、特定のシナリオにおける緊急時の対応に非常に役立ちます。

プログラムが以下のインターフェースを呼び出すと、システムからCPU使用率100%の警告が出ました。このような状況では、Arthasを使用して特定のシナリオにおける緊急事態に対処できます。

 @RequestMapping("cpu-100") public static void cpu() { //无限循环输出打印new Thread(() -> { while (true) { log.info("cpu working"); } }, "thread-1").start(); }

`thread` コマンドを使用して、thread-1 が基本的に単一の CPU でフル稼働していることを観察し、コンソールを使用して対応する ID が 48 であることを確認しました。

この時点で、`vmtool` の `action` コマンドを使用してスレッドを中断できます。

 vmtool --action interruptThread -t 48

操作が完了すると、スレッドが正常に中断されたことがわかります。

vmTool は変数の詳細の監視もサポートしています。次のインスタンス変数 dateTimeStr を例に挙げると、API リクエストごとにリアルタイムで更新されます。

 private String dateTimeStr = DateUtil.formatDateTime(new Date()); @RequestMapping(value = "/getVal") public String getVal() { dateTimeStr = DateUtil.formatDateTime(new Date()); log.info("dateTimeStr: {}", dateTimeStr); return "success"; }

dateTimeStr の現在の値を表示する場合は、vmtool のアクションを getInstances として指定し、クラスの完全なパス (この例では com.example.arthasExample.TestController) を指定して、最後に式 instances[0].dateTimeStr を入力します。これは、現在のインスタンスの dateTimeStr を取得することを意味します。

 vmtool --action getInstances --className com.example.arthasExample.TestController --express 'instances[0].dateTimeStr'

この時点で、この変数の情報を非常に直感的に監視できます。

面接でよく聞かれる質問: Arthas の統計手法の時間消費の背後にある基本原理は何ですか?

以下は watch コマンドの例です。

 watch com.example.MyService sayHello "{params, result, throwExp} -> { return 'Exception: ' + throwExp; }" -E

命令から、クラスのフルパスを取得できることがわかります。推測することなく、クラスのフルパスに基づくバイトコードスタブ技術を使用してクラスを拡張し、メソッド実行の前後に時間を挿入するコードを挿入することで、時間統計を実現します。