すべてのプロダクト
Search
ドキュメントセンター

Application Real-Time Monitoring Service:非同期タスクを監視するためにARMSを使用する

最終更新日:Jan 15, 2025

非同期タスクの実行中にインターフェースのタイムアウトなどのエラーが発生した場合、トレースをクエリして非同期タスクのアップストリームサービスとダウンストリームサービスを確認できます。これにより、できるだけ早くエラーをトラブルシューティングできます。デフォルトでは、Application Real-Time Monitoring Service (ARMS) を使用して、Spring Boot で @Async アノテーションを使用して作成された非同期タスクを監視できます。さらに、ARMS では、非同期パススルーのスキャンパッケージを追加するか、手動パススルーに ARMS SDK を使用することにより、カスタム非同期タスクを監視できます。

前提条件

ARMS エージェントは V2.7.1.3 以降です。 ARMS エージェントの更新方法の詳細については、「ARMS エージェントの更新」をご参照ください。

説明

ARMS エージェント V4.x 以降は、追加設定なしで、このトピックで説明されている非同期タスクを監視するために使用できます。他の非同期シナリオでコンテキストを渡すには、「Java 用 OpenTelemetry SDK を使用してプロセス固有のコンテキストを非同期に渡す」をご参照ください。

監視

デフォルトでは、ARMS は @Async アノテーションを使用して作成された非同期タスクを自動的に監視します。 ARMS は、Spring の次のデフォルトのエグゼキューターとタスクを自動的に拡張します。

  • エグゼキューター:

    • org.springframework.scheduling.concurrent.ConcurrentTaskExecutor

    • org.springframework.core.task.SimpleAsyncTaskExecutor

    • org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor

    • org.springframework.core.task.support.TaskExecutorAdapter

    • org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor

    • org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler

    • org.springframework.jca.work.WorkManagerTaskExecutor

    • org.springframework.scheduling.commonj.WorkManagerTaskExecutor

  • タスク:

    • org.springframework.aop.interceptor.AsyncExecutionInterceptor$1

    • org.springframework.aop.interceptor.AsyncExecutionInterceptor$$Lambda$

カスタム非同期タスクを監視する

非同期パススルーのスキャンパッケージを追加する

非同期タスクを監視するために、アプリケーションの構成に非同期パススルーのスキャンパッケージを追加できます。 Runnable オブジェクト、Callable オブジェクト、または Supplier オブジェクトが作成されると、非同期パススルーのスキャンパッケージ内の対応するメソッドが現在のスレッドのトレースコンテキストを自動的にキャプチャします。次に、スレッドが非同期モードで使用されると、メソッドはキャプチャされたトレースコンテキストをスレッドに渡します。

  1. ARMS console にログインします。左側のナビゲーションペインで、[アプリケーション監視] > [アプリケーションリスト] を選択します。

  2. [アプリケーションリスト] ページで、上部のナビゲーションバーでリージョンを選択し、管理するアプリケーションの名前をクリックします。

    説明

    [言語] 列に表示されるアイコンは、アプリケーションが記述されている言語を示します。

    Java图标: Java アプリケーション

    image: Go アプリケーション

    image: Python アプリケーション

    ハイフン (-): Managed Service for OpenTelemetry で監視されるアプリケーション。

  3. 左側のナビゲーションペインで、[アプリケーション設定] をクリックします。表示されるページで、[カスタム構成] タブをクリックします。

  4. タブの [詳細設定] セクションで、[非同期透過伝送スキャンパッケージ名] フィールドに非同期パススルーのスキャンパッケージの名前を入力します。

    异步透传扫描包

  5. [保存] をクリックします。

重要

構成を有効にするには、アプリケーションを再起動する必要があります。複数の非同期パススルーのスキャンパッケージを追加するには、パッケージ名をコンマ (,) で区切ります。

たとえば、非同期パススルーのスキャンパッケージを使用して、次のサンプルコードを使用して作成された非同期タスクを監視できます。サンプルの非同期パススルーのスキャンパッケージのフルネームは com.alibaba.arms.brightroar.console.service です。

重要
  • アプリケーション構成に非同期パススルーのスキャンパッケージを追加する場合、必要に応じて指定されたパッケージ名を調整できます。多数の非同期タスクを監視する場合は、完全なパッケージ名ではなく、パッケージ名のプレフィックスを指定できます。この例では、[非同期透過伝送スキャンパッケージ名] フィールドに、完全なパッケージ名 com.alibaba.arms.brightroar.console.service またはプレフィックス com.alibaba.arms を入力できます。プレフィックス com.alibaba.arms を入力すると、このディレクトリ内のすべての非同期パススルーのスキャンパッケージが監視に使用されます。ただし、短いプレフィックスは、過度に多数の非同期パススルーのスキャンパッケージを伴う可能性があり、パフォーマンスの低下につながります。パッケージ名を指定する際は注意してください。

  • ラムダ式を Runnable オブジェクトとしてスレッドプールに送信すると、重複したトレース ID が生成される可能性があります。式を送信するために匿名オブジェクトを作成することをお勧めします。 ARMS エージェント V4.0 以降では、重複したトレース ID が修正されています。

package com.alibaba.arms.brightroar.console.service;

@Service
public class NameService {

    private ExecutorService es = Executors.newFixedThreadPool(5);

    public void name() {
        es.submit(new Runnable() {
            @Override
            public void run() {
                // 現在の時刻とスレッドIDを出力します。
                System.out.println(System.currentTimeMillis()+ ": my name is john, " + Thread.currentThread().getId());
            }
        });
    }
}

ARMS SDK を使用して手動パススルーを実装する

上記のメソッドが複雑な監視シナリオでの要件を満たせない場合は、ARMS SDK を使用して手動パススルーを実装できます。 Runnable メソッドと Callable メソッド、およびエグゼキューターを拡張して、非同期スレッドのトレースを連結し、非同期タスクを監視できます。

  1. Maven プロジェクトの pom.xml ファイルに次の依存関係を追加します。

    <dependency>
     <groupId>com.alibaba.arms.apm</groupId>
     <version>1.7.5</version>
     <artifactId>arms-sdk</artifactId>
    </dependency>
  2. 必要に応じて、Runnable メソッドと Callable メソッド、およびエグゼキューターを拡張します。必要に応じて、次の拡張メソッドのいずれかを使用できます。

    メソッド 1: Runnable メソッドと Callable メソッドを拡張する

    TraceRunnable.asyncEntry() メソッドを呼び出して、Runnable メソッドを強化します。TraceCallable.asyncEntry() メソッドを呼び出して、Callable メソッドを強化します。次のコードは、Runnable メソッドと Callable メソッドを強化する方法の例を示しています。

    public class AsyncEntryExample {
    
        private final ExecutorService executor = Executors.newSingleThreadExecutor();
    
        @GetMapping(value = "/sdk-async-plugin/asyncEntry-propagation")
        public String asyncEntryAndExecute() throws Exception {
            CompletableFuture<String> future = new CompletableFuture<>();
            Runnable command = TraceRunnable.asyncEntry(() -> future.complete("asyncEntry-execute"));
            executor.execute(command);
            Thread.sleep(1000);
            return future.get();
        }
    }

    メソッド 2: エグゼキューターを拡張する

    TraceExecutors.wrapExecutorService(executor, true) メソッドを呼び出して、executor を強化します。次のコードは、executor を強化する方法の例を示しています。

    public class AutoExample {
    
        private final ExecutorService contextPropagationExecutor
                = TraceExecutors.wrapExecutorService(Executors.newSingleThreadExecutor(), true);
    
        @GetMapping(value = "/sdk-async-plugin/auto-context-propagation")
        public String autoWrapAndExecute() throws Exception {
            CompletableFuture<String> future = new CompletableFuture<>();
            contextPropagationExecutor.execute(() -> future.complete("auto-execute"));
            Thread.sleep(1000);
            return future.get();
        }
    }

    メソッド 3: Runnable メソッドと Callable メソッド、およびエグゼキューターを拡張する

    次のコードは、Runnable メソッドと Callable メソッド、およびエグゼキューターを拡張する方法の例を示しています。

    public class ManualExample {
        private final ExecutorService traceExecutor
                = TraceExecutors.wrapExecutorService(Executors.newSingleThreadExecutor());
    
        @GetMapping(value = "/sdk-async-plugin/manual-context-propagation")
        public String manualWrapAndExecute() throws Exception {
            CompletableFuture<String> future = new CompletableFuture<>();
            traceExecutor.execute(TraceRunnable.wrap(() -> future.complete("manual-execute")));
            traceExecutor.execute(() -> "Not captured"); // キャプチャされない
            Thread.sleep(1000);
            return future.get();
        }
    }

結果

構成が完了すると、トレース詳細ページで非同期タスクのトレース詳細を表示できます。詳細については、「トレースクエリ」をご参照ください。