Java Spring Integration アプリケーション の計装
この記事では、Open Telemetry と X-ray を利用して Spring-Integration アプリケーションを手動で計装するアプローチについて説明します。
Spring-Integration フレームワークは、イベント駆動型アーキテクチャやメッセージング中心のアーキテクチャに典型的な統合ソリューションの開発を可能にするように設計されています。 一方、OpenTelemetry は、サービスが HTTP リクエストを使用して相互に通信および調整するマイクロサービスアーキテクチャに重点を置く傾向があります。 そのため、このガイドでは OpenTelemetry API を使用した手動計装により Spring-Integration アプリケーションを計装する方法の例を提供します。
背景情報
トレーシングとは何か?
OpenTelemetry のドキュメント からの以下の引用は、トレースの目的に ついて良い概要を示しています:
トレースは、アプリケーションにリクエストが行われたときに何が起こるかの全体像を示します。アプリケーションが単一のデータベースを持つモノリスであっても、洗練されたサービスメッシュであっても、トレースはアプリケーション内でリクエストが辿る完全な「パス」を理解するために不可欠です。
トレーシングの主な利点の 1 つがリクエストのエンドツーエンドの可視性であることを考えると、リクエストの発信元からバックエンドまで、トレースが適切にリンクすることが重要です。OpenTelemetry でこれを行う一般的な方法は、ネストされたスパン を利用することです。これは、スパンがサービスからサービスへと最終目的地に到達するまで渡されるマイクロサービスアーキテクチャで機能します。Spring Integration アプリケーションでは、リモートとローカルの両 方で作成されたスパン間に親子関係を作成する必要があります。
コンテキスト伝播を利用したトレーシング
コンテキスト伝播を使用するアプローチを紹介します。このアプローチは通常、ローカルおよびリモートの場所で作成されたスパン間に親子関係を作成する必要がある場合に使用されますが、Spring Integration アプリケーションの場合にも使用されます。これはコードを簡素化し、アプリケーションのスケーリングを可能にするためです。複数のスレッドでメッセージを並列処理することが可能になり、異なるホストでメッセージを処理する必要がある場合に水平方向にスケールすることも可能になります。
これを実現するために必要なことの概要は以下の通りです:
-
ChannelInterceptor
を作成し、GlobalChannelInterceptor
として登録して、すべてのチャンネルで送信されるメッセージをキャプチャできるようにします。 -
ChannelInterceptor
内で:preSend
メソッドで:- 上流で生成される前のメッセージからコンテキストを読み取ろうとします。これにより、上流のメッセージからのスパンを接続できます。コンテキストが存在しない場合は、新しいトレースが開始されます(これは OpenTelemetry SDK によって行われます)。
- その操作を識別するユニークな名前でスパンを作成します。これはメッセージが処理されているチャンネルの名前にすることができます。
- 現在のコンテキストをメッセージに保存します。
- コンテキストとスコープを thread.local に保存し、後で閉じることができるようにします。
- 下流に送信されるメッセージにコンテキストを注入します。
afterSendCompletion
で:- thread.local からコンテキストとスコープを復元します。
- コンテキストからスパンを再作成します。
- メッセージの処理中に発生した例外を登録します。
- スコープを閉じます。
- スパンを終了します。
これは必要な作業の簡略化された説明です。Spring-Integration フレームワークを使用した機能的なサンプルアプリケーションを提供しています。このアプリケーションのコードはこちらで見つけることができます。
アプリケーションを計測するために行われた変更のみを表示するには、この差分を参照してください。
このサンプルアプリケーションを実行するには、以下を使用します:
# ビルドと実行
mvn spring-boot:run
# サンプル入力ファイルを作成してフローをトリガーする
echo 'testcontent\nline2content\nlastline' > /tmp/in/testfile.txt
このサンプルアプリケーションを試すには、アプリケーションと同じマシンで ADOT コレクター を実行する必要があります。以下のような設定を使用します:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch/traces:
timeout: 1s
send_batch_size: 50
batch/metrics:
timeout: 60s
exporters:
aws xray: region:us-west-2
aws emf:
region: us-west-2
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch/traces]
exporters: [awsxray]
metrics:
receivers: [otlp]
processors: [batch/metrics]
exporters: [awsemf]
結果
サンプルアプリケーションを実行し、以下のコマンドを実行すると、次のような結果が得られます:
echo 'foo123\nbar123\nfoo1234' > /tmp/in/testfile.txt
上記のセグメントが、サンプルアプリケーションで説明されているワークフローと一致していることがわかります。 一部のメッセージの処理中に例外が発生することが予想されるため、それらが適切に登録され、X-Ray でトラブルシューティングできるようになっていることがわかります。
よくある質問
ネストされたスパンをどのように作成しますか?
OpenTelemetry には、スパンを接続するために使用できる 3 つのメカニズムがあります: