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 フレームワークを使用する機能的なサンプルアプリケーションを提供しています。このアプリケーションのコードは こちら にあります。
アプリケーションを計装するために行われた変更のみを表示するには、この diff を参照してください。
このサンプルアプリケーションを実行するには以下を使用します。
# build and run
mvn spring-boot:run
# create sample input file to trigger flow
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 でトラブルシューティングできることがわかります。