Javaアプリケーション監視(7) - 行動的診断アーチファクトBTrace

タグ:javaの、トラブルシューティング、監視、btrace


一つの文にまとめた:BTrace、あなたが前提のアプリケーション検出コード操作でアプリケーションコード、ノンストップサービスを変更して、問題を診断することなく、それが生産環境に不可欠な強力なJavaのオンラインアプリケーション検出ツール(ダイナミック追跡ツール)であることができていますアーティファクト、この記事では、その使用について説明します。

1はじめに

BTraceそれは、オープンソースソフトウェアgithubアドレス:https://github.com/btraceio/btraceある公式サイトを紹介しBTrace is a safe, dynamic tracing tool for the Java platform.、それが動的にバイトコードの目標追跡アプリケーションにコードを挿入することができ、動的追跡ツールのJavaアプリケーションに安全です、。ダイナミックとは何ですか?我々は、すべてのJavaアプリケーションの起動がいつことを知っているclassために、ファイルのロードJVMを実行し、このタイムclassコード機能は、コードを変更するために、(変更しない)、静的なだけで、展開、再コンパイルを開始、変更することができるかを決定することです。

オンラインアプリケーションを扱うときと、私たちはしばしば、コードの動作を見てパラメータ値を必要とする、本番環境で表示したり、などのデバッグログに独自の必要性を追加し、開発段階で、ログを追加し、問題なく再起動しますが、ないに戻り(本番環境は、一般的にサービスを停止することは容易ではない、とでも再開することができ、問題が問題を再現することができませんでしオンサイトの破壊を、発生する可能性があります)を適用し、その方法は、実行するJavaアプリケーションの中に存在する場合、プログラムを再起動せずに、ダイナミックに追加私は、コンテンツの(トラック)を監視したいですか?Btraceそのようなアーティファクトは、動的追跡場合に再起動せずにアプリケーションの動作を監視することができ、プログラムデータは、実行時、メソッドパラメータ、戻り値、グローバル変数で取得した情報をスタックすることができるされています。この記事では、のためにあるBTrace動作や原理の使用について説明します。

2 BTrace動作原理

動的2.1クラスファイルを置き換える修正

BTrace達成するためのJavaベースの動的トラッキング技術です。Java開発者のために、Javaプログラムの開発プロセスは明らかに、Javaコードを記述したクラスファイルのためにそれをコンパイルして、しているJVMロードされたクラスを実行します。あなたがアプリケーションを停止せずに、この時間をしたい場合はclass、このような方法のように、コンテンツを追加するように変更トラックを(method主に二つのことを、出力を追加します):

  • (1)変更がにロードされているJVMカスタムの出力を追加し、クラス
  • JVM`で実行クラスの(2)の交換

最初のステップは、原因に、修正JVM直接バイトコード変更されていない、すべてのクラスファイルの操作classライン(もちろん、読み込み可能なバイトコードファイルのJavaコードがはるかに高くなっている)上のファイルを、すでに対応するフレームワークがあります私たちは、これがすることです行うことができASM、このフレームワークを使用し、直接など、それはまた、動的に新しいクラスを作成している私たちは簡単に変更するクラスを注入することによって、バイトコードファイルを操作することを可能にするインターフェースを提供し、フレームのバイトコードを編集することができますように。Springこれは、動的プロキシを達成するために、この技術を使用することです。

第二段階、交換してください、あなたが提供されているJavaを使用する必要がある場合は交換しjava.lang.instrument.Instrumentation、それは2つのインタフェースを有しているredefineClassesretransformClassesredefineClasses既存のファイルを置き換えるために、独自のクラスのバイトコードファイルを提供、retransformClassesすでに存在するバイトコード変更し、ファイルを置き換えます。しかし、それは、と指摘するinstrument(など、追加、変更、フィールドやメソッドは、メソッドのシグネチャを変更していない削除、継承されたプロパティを変更することはできません)の使用が制限されました:

The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance
复制代码

実行中のプロセスを2.2 BTraceモジュール

BTraceは、物品、達成するために、以前の技術に基づいており、「Javaの動的トラッキング技術の照会」()https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA以下に簡単に説明し、ダイナミックトラッキング技術については詳細に記載されています。

メインモジュール2.2.1

  • BTraceスクリプト:必要に応じてBTrace定義されたアノテーションを使用し、我々は簡単にスクリプトを開発することができます。

  • コンパイラ:BTraceクラスファイルにコンパイルBTraceスクリプト。

  • クライアント:クラスのエージェントにファイルを送信します。

  • エージェントは:JavaベースAttach API-実行中のエージェント、動的に取り付けることができるJVM上、その後のターンはBTrace Server、スクリプトを解析して、スクリプトベースのルールに従って変更されることが判明、バイトコードの呼び出しを変更し、送信し、クライアントスクリプトBTraceを受けインタフェースは、オブジェクトの動作に影響を取り、修正を行います。Java Instrumentretransform

2.2.2実行プロセス

以下のフローチャートを実行します。

Javaソースコードのように、あなたの書くBtraceスクリプト(また、Javaファイルを)、(コンパイルcompiler)、クライアントから送信されたagentagentによって、attach apiJVMに追加し始めるagent server受信するclientコンテンツは、底が使用され、オーバー送られたASM修正バイトコードファイルを、次に使用するインタフェースを代わりに変更されたクラスファイル、出力を通じて実行した後に送られたディスプレイ。Java Instrumentretransformagentclient

3 BTraceインストール

知っているBTrace動作の原理を、インストール慣行は今見ることができます。まだこの論文の例java-monitor-exampleBTraceインストールは、箱から出して、非常に簡単です。

  • ダウンロード(現在のバージョンです[v1.3.11.3]):https://github.com/btraceio/btrace/releases
  • Javaアプリケーションサーバーを抽出するために、どこで監視します
  • btraceでコマンドbinディレクトリ
  • あなたが任意のディレクトリで実行する必要がある場合は、する必要がありますbtrace(環境変数を設定しますexport

4つのBTraceアプリケーションシナリオ

基本的に、BTraceそれが有する前述れるなど、継承、変更、削除方法は、プロパティを追加することができない、唯一の出力ダイナミック・トラッキング・クラスに適用されるInstrument制限は、同じです。一般的に、使用Btraceのいくつかに基づいて、シーンの大部分を含んで、クラスのログ出力に属し、オンライン監視アプリケーションのために:

  • 一つのプロセスパラメータと戻り値に参照してください。
  • 特定のメソッドの応答時間を確認してください
  • 実行するコードの行があるかどうかを参照してください。
  • 印刷システムのパラメータ、またはJVMの起動パラメータ
  • 印刷方法は、スレッドのスタックを呼び出します
  • 例外が発生した場合に異常情報を印刷

5 BTraceの使用

Btraceスタンドアロンツールとして、デフォルトではローカルでのみ実行することができ、それは言うことです、あなたはJavaアプリケーションがモニターを実行したいものは、対応するサーバーにそれを解凍する必要があります。この例では実行されjava-monitor-example、スクリプトを記述し、出力を参照するには、スクリプトを実行して、Javaアプリケーションを監視する必要があるとして、および監視は、ビジネスニーズに基づいています。

5.1スクリプティング

5.1.1ノートとBTraceUtils

BtraceJavaのスクリプトやコードを書くには違いはありませんが、多くの比較的単純な、主に使用してBtrace提供されたアノテーションをしてBTraceUtils、注釈を伝えるために使用されBtrace、場所を傍受する傍受するクラスの必要性と遮断機会をBTraceUtils情報機能のプリントアウトの種類を提供するため。次の例では、公式サイトを与えられます:

package samples;

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

/**
 * This script traces method entry into every method of 
 * every class in javax.swing package! Think before using 
 * this script -- this will slow down your app significantly!!
 */
@BTrace public class AllMethods {
    @OnMethod(
        clazz="/javax\\.swing\\..*/",
        method="/.*/"
    )
    public static void m(@ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
        print(Strings.strcat("entered ", probeClass));
        println(Strings.strcat(".", probeMethod));
    }
}
复制代码

上記のコードは、すべて傍受の呼び出しと言ったjavax.swing方法の始まり、その後は、クラス名やメソッド名をプリントアウト。注釈があることに留意することができ@BTrace@OnMethod@ProbeClassName@ProbeMethodName、むしろprintprintlnそれはBTraceUtils静的な方法を提供します。BTraceUtilsこれは、多くの印刷方法(例は後述する)を提供します。また、トラッキング動作は静的メソッドの本体を指定する必要があることに注意し、したがってする必要がstatic近づきます。

また、に関してBTraceの参照を提供ノートかもしれ公式文書https://github.com/btraceio/btrace/wiki/BTrace-Annotations)。次のものがあります。

/**Class Annotations*/
@com.sun.btrace.annotations.DTrace
@com.sun.btrace.annotations.DTraceRef
@com.sun.btrace.annotations.BTrace
/**Method Annotations*/
@com.sun.btrace.annotations.OnMethod
@com.sun.btrace.annotations.OnTimer
@com.sun.btrace.annotations.OnError
@com.sun.btrace.annotations.OnExit
@com.sun.btrace.annotations.OnEvent
@com.sun.btrace.annotations.OnLowMemory
@com.sun.btrace.annotations.OnProbe
/**Argument Annotations*/
@com.sun.btrace.annotations.Self
@com.sun.btrace.annotations.Return
@com.sun.btrace.annotations.CalledInstance
@com.sun.btrace.annotations.CalledMethod
/**Field Annotations*/
@com.sun.btrace.annotations.Export
@com.sun.btrace.annotations.Property
@com.sun.btrace.annotations.TLS

复制代码

これは、@OnMethodより多くのと、主に3つのプロパティであることを説明することが重要であるclazzmethodlocation

  • clazz次のようなクラスのフル・パス名、me.mason.monitor.controller.UserController

  • method:のような、メソッド名を監視するにはgetUsers

  • location:使用する傍受機会@Location注釈を。

@Location以下があります。

  • Kind.ENTRY:メソッドに入ると呼び出し
  • Kind.RETURN:メソッドを呼び出す終了すると、定義された唯一のインターセプト位置Kind.RETURN方法を得るためには、結果を返し@Return、実行時間@Duration
  • Kind.CALL:他のメソッドの呼び出しを呼び出すとき
  • Kind.LINE:指定された場所にコードかどうかを監視するために、ラインを設定することにより
  • Kind.ERROR, Kind.THROW, Kind.CATCH:トラッキング異常事態

書き込みの5.1.2

書くための勧告またはJava Mavenプロジェクトの開発環境を使用するには、コードヒントを使用することができます。そして、サーバを監視するために、対応する必要性に書き込まれました。しかし、あなたは、対応するjarファイルのパッケージ(編集する際に参照する必要があるbtrace-agentbtrace-bootbtrace-clientダウンロードしたインストール中のjar対応)、buildディレクトリを。pom.xml導入それは使用することができます。次のように:

<!-- BTrace -->
<dependency>
    <groupId>com.sun.btrace</groupId>
    <artifactId>btrace-agent</artifactId>
    <version>1.3.11.3</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>E:/btrace-bin-1.3.11.3/build/btrace-agent.jar</systemPath>
</dependency>
<dependency>
    <groupId>com.sun.btrace</groupId>
    <artifactId>btrace-boot</artifactId>
    <version>1.3.11.3</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>E:/btrace-bin-1.3.11.3/build/btrace-boot.jar</systemPath>
</dependency>
<dependency>
    <groupId>com.sun.btrace</groupId>
    <artifactId>btrace-client</artifactId>
    <version>1.3.11.3</version>
    <type>jar</type>
    <scope>system</scope>
    <systemPath>E:/btrace-bin-1.3.11.3/build/btrace-client.jar</systemPath>
</dependency>
复制代码

5.2スクリプト

印刷ヘルプ情報は次のとおりです。

一般的には、サーバ上で、直接IS btrace PID btraceFile.java、出力(出力のようなファイルの内容を、次いでを見ることができる見てbtrace PID btraceFile.java > info.txt)。あなたが特定のjarファイルパッケージを使用している場合は、パラメータに置く必要があるcpclasspathプラス。以下の例では、メソッド呼び出しが値出力を返しています。

5.3スクリプト例

説明するために、いくつかの一般的な例に従うことによりBTrace、スクリプトの使用、例えば、プロジェクト内のスクリプトjava-monitor-examplebtraceディレクトリを。java-monitor-exampleそれぞれ、Aがcontrollerservice、メソッド定義がある、次の動的追跡は、これらの方法に基づいて説明します。

/**
  * UserController.java
  **/
@GetMapping("/user")
public ResponseResult<User> getUser() {
    User user = userService.getUser();
    return ResponseResult.ok(user);
}

@GetMapping("/users")
public ResponseResult<User> getUsers(int num) {
    List<User> users = userService.getUsers(num);
    return ResponseResult.ok(users);
}

/**
  * UserService.java
  * 根据ID获取用户
  *
  * @return
  */
public User getUser() {
    return mockUser();
}

/**
  * 获取用户数组
  *
  * @return
  */
public List<User> getUsers(int num) {
    userList.clear();
    for(int i=0 ; i < num; i++){
        userList.add(mockUser());
    }
    return userList;
}
复制代码

5.3.1印刷方法情報

  • (メソッド呼び出し時に印刷パラメータを呼び出しUserControllergetUsers印刷をする場合の方法)
@OnMethod(clazz = "me.mason.monitor.controller.UserController"
          ,method = "getUsers",location = @Location(Kind.ENTRY))
public static void readFunction(@ProbeClassName String className, @ProbeMethodName String methodName, AnyType[] args) {
    // 打印时间
    BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
    BTraceUtils.println("method controller");
    BTraceUtils.printArray(args);
    BTraceUtils.println(className + "," + methodName);
    BTraceUtils.println("==========================");
}
复制代码
  • 印刷のメソッドを呼び出し、戻り値
@OnMethod(clazz = "me.mason.monitor.service.UserService"
,method = "getUsers",location = @Location(Kind.RETURN))
public static void printReturnData1(@Return AnyType result){
    BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
    BTraceUtils.printFields(result);
    BTraceUtils.println("==========================");
    BTraceUtils.println(BTraceUtils.str(result));
    BTraceUtils.println("==========================");
}
复制代码
  • (かどうかを確認するために実行の実装に行数UserService行39)
@OnMethod(clazz = "me.mason.monitor.service.UserService"
,method = "getUsers",location = @Location(value = Kind.LINE,line = 39))
public static void printLineData(@ProbeClassName String className, @ProbeMethodName String methodName,int line){
    BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
    BTraceUtils.println(className + "," + methodName + ","+line);
    BTraceUtils.println("==========================");
 }
复制代码
  • ときに使用される方法の実行(長い使用方法)UserControllergetUsers
@OnMethod(clazz = "me.mason.monitor.controller.UserController"
,method = "getUsers",location = @Location(Kind.RETURN))
public static void getUsersDuration(@Duration long duration){
    BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
    BTraceUtils.println("time(ns):" + duration);
    BTraceUtils.println("time(ms):" + BTraceUtils.str(duration / 1000000));
    BTraceUtils.println("time(s):" + BTraceUtils.str(duration / 1000000000));
    BTraceUtils.println("==========================");
}
复制代码

5.3.2 JVM印刷システムのプロパティと属性

同様にJDK、コマンドラインツールjinfo、加えて、jmapそしてjstatck公式の例で見つけることができます。

@BTrace
public class JInfo {
    static {
        println("System Properties:");
        printProperties();
        println("VM Flags:");
        printVmArguments();
        println("OS Enviroment:");
        printEnv();
        exit(0);
    }
}
复制代码

5.3.3印刷出力異常

java開発者がいることを知っておくべきjava異常を分割ErrorしてException、彼らがしている間、Throwableサブカテゴリー、すなわち、javaあるすべての例外の親クラスではThrowable、このコンストラクタを追跡し、あなたがして、スタックをプリントアウトすることができます。次のように:

//局部变量存储异常
@TLS static Throwable currentException;
//异常构造函数开始
@OnMethod(
    clazz="java.lang.Throwable",
    method="<init>"
)
public static void onthrow(@Self Throwable self) {
    currentException = self;
}
//异常构造函数结束,输出堆栈
@OnMethod(
    clazz="java.lang.Throwable",
    method="<init>",
    location=@Location(Kind.RETURN)
)
public static void onthrowreturn() {
    if (currentException != null) {
        Threads.jstack(currentException);
        println("=====================");
        currentException = null;
    }
}
复制代码

5.4スクリプトの制限

BTraceバイトコードが、主に情報の要求出力、及びプログラムの正常な動作に影響を修飾がJVMは、「読み取り専用」、BTraceをそれを行うことです。動的置換クラスファイルので、修飾バイトコードが自動的に復元されていないことに留意されたいです。関係者はまた、文書を記述BTraceスクリプトは次の制限があります。

  • オブジェクトを作成することは許されません

  • 配列を作成することはできません

  • 例外をスローすることはできません

  • 異常をキャッチすることはできません

  • 静的メソッドは、呼び出しのcom.sun.btrace.BTraceUtilsが提供のみを許可し、他のオブジェクトやクラスのメソッドを呼び出すことはできません(一部のデータ処理と情報出力手段)

  • クラスのプロパティを変更することはできません

  • メンバ変数やメソッドを許可していない、唯一の静的パブリックvoidメソッドを可能に

  • これは、内部クラス、ネストされたクラスを許可していません

  • この方法は、同期と同期のブロックを許可していません

  • それは循環を許可していません

  • (java.lang.Object上位を除いて、もちろん)他のクラスから継承することはできません。

  • インターフェイスを実装することはできません。

  • 許可されていませんアサート

  • Classオブジェクトが許可されていません

6いくつかの経験

  • コードヒントを提供するために、スクリプトの開発環境、対応するjarファイルの導入を構築するためにJavaのMavenプロジェクトを使用してください。
  • 公式が提供するビューの例は、ダウンロードパッケージ内の位置の例を提供していますbtrace-bin-1.3.11.3\samplesカタログを
  • BTrace入力パラメータを追跡するスクリプトは、戻り値の型は、複合型を使用することができます直接使用する単純型(たとえば、int型、float型、など)でAnyType、時間を追加したが、彼らは(Userなど)のカスタムパッケージの種類を使用している場合は、スクリプトを実行する必要がありますcpclasspathパラメータは、カスタムパッケージを指定します。
  • 通常、単純型または文字列、直接printまたはprintln、オブジェクトのプロパティは、印刷するために使用され得るprintFields、印刷List、使用することができますBTraceUtils.println(BTraceUtils.str(list))
  • プローブ法に最後の行で分離されたプリントが、それを強くお勧めします。出力は分離されていない場合、分離されていないコンテンツ後の出力または出力がない場合があり、出力バッファ遅延に起因するがあってもよいです。パーティションを使用することができますBTraceUtils.printlnBTraceUtils.println("============")

7概要

あなたが問題を診断するためにノンストップサービスのログ出力をしたい場合は、オンラインでのJavaアプリケーションについては、ダイナミックトラッキング技術は必要不可欠な技術である、とBtraceの強力なツールを追跡する動的な達成するために、この技術を使用しています。以下からのBtrace動作原理、インストール、アプリケーションのシナリオ、スクリプト、実行し、その詳細な説明、の側面は、あなたが深めしたいと考えてBtrace、オンラインの問題を解決するために、より便利で効率的な、理解を。

データシート

  • BTrace公式サイト:https://github.com/btraceio/btrace
  • BTrace注意:https://github.com/btraceio/btrace/wiki/BTrace-Annotations
  • サンプルコード住所:https://github.com/mianshenglee/my-example/tree/master/java-monitor-example
  • 探索するためのJavaの動的トラッキング技術:https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA
  • BTrace原理に:https://www.rowkey.me/blog/2016/09/20/btrace/

関連読書

おすすめ

転載: juejin.im/post/5d691a036fb9a06af92bb946