Java Spring Integration アプリケーションの計装
この記事では、Spring-Integration アプリケーションを Open Telemetry と X-ray を使用して手動で計装するアプローチについて説明します。
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 フレームワークを使用する機能的なサンプルアプリケーションを提供しています。このアプリケーションのコードはこちらで確認できます。
アプリケーションの計装に加えられた変更のみを確認するには、この差分をご覧ください。