分散トレース@テレメトリー¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. 分散トレース¶
分散トレースとは¶
マイクロサービスから収集されたスパンのセットのこと。
スパンをトレースIDで紐付けることによって、1
個のリクエストで発生したマイクロサービスを横断する処理を、一繋ぎに表現できるようになる。
- https://www.dynatrace.com/news/blog/open-observability-part-1-distributed-tracing-and-observability/
- https://docs.newrelic.com/jp/docs/distributed-tracing/concepts/introduction-distributed-tracing/
- https://medium.com/nikeengineering/hit-the-ground-running-with-distributed-tracing-core-concepts-ff5ad47c7058
- https://www.aspecto.io/blog/jaeger-tracing-the-ultimate-guide/
分散トレースの用途¶
▼ レスポンスタイムの最適化¶
分散トレースを収集すると、マイクロサービス間のレスポンスタイムを可視化できる。
例えば、性能テストでシステム全体の性能のデグレーションがあったとする。
分散トレースで特定のマイクロサービス間でレスポンスタイムを可視化できるため、いずれのマイクロサービス間の通信がボトルネックになっているかがわかる。
そのダウンストリーム側マイクロサービスのリクエストまたはアップストリーム側マイクロサービスのレスポンスに関して、性能に問題がないかを調査する必要がある。
▼ 悪意のあるリクエストの検出¶
分散トレースを収集すると、悪意のあるリクエストを検出できる。
例えば、特定のマイクロサービスへのリクエストが異常に多ければ、そのマイクロサービスに悪意のあるリクエストが送信されている可能性がある。
分散トレースの読み方¶
上から下に読むと、ダウンストリーム側マイクロサービス (上位スパン) がアップストリーム側マイクロサービス (下位スパン) を処理をコールしていることを確認できる。
下から上に読むと、アップストリーム側マイクロサービス (下位スパン) からダウンストリーム側マイクロサービス (上位スパン) に結果を返却していることを確認できる。
モノリシックアーキテクチャにおける分散トレース¶
モノリシックアーキテクチャなアプリケーションでは、システムが分散していないため、単なるトレースとなる。
*例*
(1)
-
a1
:クライアントがリクエストを送信する。 (2)
-
a1
:リクエストがロードバランサ-に到達する。 (3)
-
a1
~a2
:ロードバランサ-で処理が実行される。 (4)
-
a2
:ロードバランサ-がリクエストをアプリケーションにルーティングする。 (5)
-
a2
:リクエストがアプリケーションに到達する。 (6)
-
a2
~a3
:アプリケーションで処理が実行される。 (7)
-
a3
:アプリケーションがレスポンスをクライアントに返信する。
02. トレースコンテキスト¶
トレースコンテキストとは¶
各スパンに含まれる情報のこと。
- 各種ID
- マイクロサービスの属性情報
トレースコンテキスト作成の仕組み¶
ロードバランサー (例:Istio IngressGateway、AWS ALB) やAPI Gateway (例:AWS API Gateway) が最初にトレースコンテキストを作成する。
これらは、トレースコンテキストがIDが持っているかを検証する。
もしIDがなければ、スパンにIDを新しく割り当てる。
▼ IDの種類¶
トレースコンテキストには、以下のIDが含まれている。
ID | 説明 |
---|---|
トレースID | リクエストIDである。全てのマイクロサービスで同じになる。 |
スパンID | 各マイクロサービス固有の処理IDである。 全てのマイクロサービスで異なっている。 |
親スパンID | クライアントのマイクロサービスの処理IDである。クライアントが同じマイクロサービス間で同じになる。 |
▼ トレースコンテキスト伝播 (分散トレースコンテキスト伝播)¶
マイクロサービスで、受信した通信のヘッダーから分散トレースのトレースコンテキストを取得し、アウトバウンド通信のヘッダーにトレースコンテキストを渡すような、実装が必要である。
分散トレースの監視バックエンド (例:OpenTelemetry、LightStep、Jaeger、Zipkin、Datadog、AWS X-Ray) ごとに、ヘッダーからトレースコンテキストを簡単に取り出せるパッケージを使用すると良い。
インバウンド通信がHTTPプロコトルでアウトバウンド通信が、gRPCによるHTTPリクエストである場合も、ヘッダー間での受け渡しが必要である。
▼ 異なる言語間での受け渡し¶
- 異なる言語の各アプリで、計装パッケージによるTracerProviderのセットアップやスパンの作成は必要
- 言語間で計装パッケージのトレースコンテキスト仕様は標準化されているため、言語が違ってもCarrierからトレースコンテキストの情報 (スパンID、トレースIDなど) を抽出したり注入したりできる
トレースコンテキスト仕様の種類¶
▼ 一覧¶
トレースコンテキストにはいくつかの仕様があり、仕様ごとにCarrierやデータ形式が異なる。
- W3C Trace Context
- W3C Baggage
- B3 (Zipkin)
- Jaeger
- 独自仕様 (AWS X-Ray、Datadog、LightStepなど)
▼ W3C Trace Context¶
W3C Trace Context仕様のIDは以下の通りである。
項目 | 値 |
---|---|
trace-id | 32 進数 |
parent-id | 16 進数 |
trace-flags | 2 進数 |
これらの値によってトレースコンテキストが決まる。
GET /foo-service HTTP/1.1
---
Host: example.com
# バージョン、トレースID、親スパンID、トレースフラグ、をリスト形式で運ぶ
traceparent: 00–0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331–01
# セッションID、特定のリクエストにのみ付与されたデータなどをリスト形式で運ぶ
tracestate: abc=00f067aa0ba902b7,xyz=99f067aa0ba902b7
▼ B3 (Zipkin)¶
B3仕様のIDは以下の通りである。
項目 | 値 |
---|---|
trace-id | 16 、32 進数 |
span-id | 16 進数 |
parent-span-id | 16 進数 |
sampling-state | サンプリング無効なら0 、有効なら1 |
これらの値によってトレースコンテキストが決まる。
GET /foo-service HTTP/1.1
---
Host: example.com
# トレースID、スパンID、サンプリングステート、親スパンID、をエンコードして運
b3: 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-1-05e3ac9a4f6e3b90
▼ X-Ray¶
X-Ray仕様のIDは以下の通りである。
項目 | 値 |
---|---|
trace-id | version (1 ) + タイムスタンプ (16 進数) + ユニークID (16 進数) |
span-id |
GET /foo-service HTTP/1.1
---
# <バージョン>-<ルートセグメントのタイプスタンプ>-<サブセグメントごとのユニークID>
trace_id: 1-58406520-a006649127e371903a2de979
ツールごとのCarrier¶
▼ Carrierとは¶
トレースコンテキストをアップストリーム側マイクロサービスに伝播させる処理を持つ。
伝播に使用する媒体 (例:HTTPヘッダー、メッセージボディ、gRPCメタデータなど) を『Carrier』という。
▼ 標準ヘッダー¶
ヘッダー名 | 説明 |
---|---|
X-REQUEST-ID |
トレースIDが割り当てられている。 |
GRPC-TRACE-BIN |
RPCによるリクエストにて、トレースIDが割り当てられている。 |
▼ zipkin系ヘッダー¶
Zipkinが使用するヘッダーを追加する。
ヘッダー名 | 説明 | 値の例 |
---|---|---|
X-B3-SAMPLED |
1 |
|
X-B3-SPANID |
スパンIDが割り当てられている。 | a2fb4a1d1a96d312 |
X-B3-TRACEID |
トレースIDが割り当てられている。 | 463ac35c9f6413ad48485a3953bb6124 |
X-B3-PARENTSPANId |
親のスパンIDが割り当てられている。ルートスパンの場合、このヘッダーは追加されない。 | 0020000000000001 |
▼ AWS X-Ray系ヘッダー¶
AWS X-Rayが使用するヘッダーを追加する。
ヘッダー名 | 説明 | 値の例 |
---|---|---|
X-AMZN-TRACE-ID |
トレースIDが割り当てられている。トレースIDはALBで作られる。 | 1-5759e988-bd862e3fe1be46a994272793 |
03. スパン¶
スパンとは¶
マイクロサービスアーキテクチャの特定のサービスにて、1つのリクエストで発生したデータのセットのこと。
スパンには親子関係があり、最上位の親スパンを『ルートスパン』ともいう。
JSON型で定義されることが多い。
SaaSツールによってJSON型の構造が異なる。
スパン名¶
スパンが作成されたクラス (構造体) やメソッド (関数) が判別しやすいようにする。
例えば、ユーザー情報を取得するマイクロサービスのスパン名として、以下の候補がある。
区切り記号は、ドット (.
) や スラッシュ(/
) が良い。
スパン名 | 構成 | 良し悪し | 補足 |
---|---|---|---|
get |
<HTTPメソッド名> |
× | |
get_account.42 |
<アプリのメソッド名>.<ID> |
× | |
get_account |
<アプリのメソッド名> |
⭕️ | スパンの属性にアカウントIDを設定するとよい。 |
get_account.accountId |
<アプリのメソッド名>.<エンドポイント名> |
⭕️ |
スパンの属性¶
領域 | 内容 | 値 |
---|---|---|
バックエンド | イベントの内容 | トレースID、スパンID、親スパンID、処理の開始時間、処理の所要時間、エラーの有無、マイクロサービスの役割名、コールされたエンドポイントなど |
ラベル | マイクロサービス名など |
スパンの粒度¶
スパンの適切な粒度は、マイクロサービスの粒度による。
マイクロサービスの粒度 | スパンの粒度 |
---|---|
境界づけられたコンテキスト | マイクロサービスごと、関数ごとに |
ルートエンティティ | マイクロサービスごと |
データポイント化¶
スパンが持つデータをデータポイントとして集計することにより、メトリクスのデータポイントを収集できる。
04. プロファイル¶
プロファイルとは¶
分散トレースのスパンにハードウェアリソース消費量の情報を加えたもの。