Dev Study
AWSサービスの内部原理 コース

73. サービスマップは観測から自動で描かれる — セグメントの集計が有向グラフになる

誰もアーキテクチャ図を描いていないのに、なぜX-Rayのコンソールにサービスの地図が現れるのか——1本1本の観測データがどう突き合わされて1枚の有向グラフになるのかを、図で追っていきます。

① 地図は集計から浮かび上がる

サービスAセグメント送信 trace=X
サービスBセグメント送信 trace=X
サービスCセグメント送信 trace=X
処理して生成
トレース共通のリクエストを持つセグメントの束
コンソールが描画
サービスグラフJSONドキュメント
サービスマップ可視化された地図
  • X-Rayは各リソースからセグメントを受け取り、「共通のリクエストを持つセグメント」をトレースにまとめ、処理してサービスグラフを生成する(公式: "X-Ray then groups segments that have a common request into traces. X-Ray processes the traces to generate a service graph")
  • 分散アプリでは「同じtrace IDを処理した全サービスのノードを1つのサービスグラフに結合する」("X-Ray combines nodes from all services that process requests with the same trace ID into a single service graph")
  • サービスグラフの実体はJSONドキュメント。コンソールがそれを使って可視化=サービスマップを生成する
  • trace IDは、リクエストが最初に到達したX-Ray対応サービスがトレーシングヘッダー(X-Amzn-Trace-Id)として付与し、下流へ伝播させる

誰かがアーキテクチャ図を手で描くのではない。各サービスが独立に送った観測(セグメント)を、同じtrace IDという共通の手がかりで突き合わせた結果として、地図が自動的に立ち上がる。

② ノードとエッジ=有向グラフ

クライアント
エッジ
ノードサービスA=セグメント送信元
ノードサービスB
推測ノードDynamoDB等
自分でセグメントを送らない下流は上流のサブセグメントから推測される
  • ノード=データをX-Rayに送る各AWSリソース。エッジ=協調して1つのリクエストを処理するサービス同士を繋ぐ("Each AWS resource that sends data to X-Ray appears as a service in the graph. Edges connect the services that work together to serve requests")
  • DynamoDBのように自分のセグメントを送らないサービスは、上流のサブセグメントから推測セグメント(inferred segment)とノードが生成される("X-Ray uses subsegments to generate inferred segments and downstream nodes")。トレースできない外部の依存でも地図に載る

これはCS基礎でいう有向グラフ——ノード(頂点)とエッジ(有向の辺)の集合そのもの。DynamoDB編でパーティションキーからノードの置き場所が決まったのと同じで、ここでもデータ構造の言葉で全体を捉えると仕組みが素直に読める。

③ 1本のエッジに2つの時間

上流サービスサブセグメント記録
体感時間=ネットワーク往復込み
グラフへの割り当て
下流サービス自分のセグメント記録
実際に働いた正確な時間
ノード下流のセグメントを使う
エッジ上流のサブセグメントを使う
  • 「サービスグラフ上のノードは常にそのサービス自身のセグメントの情報を使い(あれば)、2ノード間のエッジは上流サービスのサブセグメントを使う」("The node on the service graph always uses information from the service's segment, if it's available, while the edge between the two nodes uses the upstream service's subsegment")
  • 両方の視点が有用な理由: 「下流サービスはリクエストの作業を開始・終了した正確な時刻を記録し、上流サービスは2サービス間の移動時間を含む往復レイテンシを記録する」
  • 下流が計装済みなら、その自前セグメントが上流サブセグメント由来の推測セグメントを置き換える

同じ1本の呼び出しを、下流は「自分が働いた正味時間」、上流は「返事が返るまでの体感時間」として二重に記録する。ノードに前者・エッジに後者を割り当てることで、両者の差がそのままネットワーク遅延として図に浮かび上がる。

④ エラー分類はHTTPの意味論

ノードサービスごとにレスポンスを集計
Error4xx(400系)
あなたのせい(クライアント)
Fault5xx(500系)
こちらのせい(サーバー)
Throttle429
待って(スロットリング)
  • 公式の分類: Error=クライアントエラー(400 series)、Fault=サーバー障害(500 series)、Throttle=スロットリング(429 Too Many Requests)("Error – Client errors (400 series errors) / Fault – Server faults (500 series errors) / Throttle – Throttling errors (429 Too Many Requests)")
  • 例外発生時はスタックトレースも記録される(取得可能な場合)

API Gateway編で見たHTTPステータスコードの意味論——4xx=あなたのせい、5xx=こちらのせい、429=待って——が、そのまま観測の集計カテゴリとして再利用されている。ステータスコードを一度きちんと理解しておくと、可観測性のダッシュボードの語彙まで一気に読めるようになる。

⑤ Scorekeep: 3つの別ノード

クライアント
Lambda呼び出し(trace IDを伝播)
Web APISDK for Java
trace IDを生成
関数にtrace IDを渡す
Lambdaサービストレーシングデータを送信
Lambda関数SDK for Node.js
同じtrace IDで送信。ランダムな名前を生成する処理
  • 公式のScorekeep例: Web APIがマイクロサービス(Lambda関数)を呼んでランダムな名前を生成する。SDK for Javaがtrace IDを生成しLambda呼び出しに含め、Lambdaがトレーシングデータを送りつつ関数にtrace IDを渡し、SDK for Node.jsも同じtrace IDで送信する
  • 「結果として、API・Lambdaサービス・Lambda関数のノードが、別々だが繋がったノードとしてトレースマップに現れる」("nodes for the API, the Lambda service, and the Lambda function all appear as separate, but connected, nodes on the trace map")

Lambda編で見たプロセス分離が、地図の上では「Lambdaサービス」と「Lambda関数」という2つの別ノードとして素直に表れる。同じ1本のtrace IDが3つのサービスを貫くことで、境界をまたいだ1本の道として繋がって描かれる。

⑥ グループ: トレースからメトリクス

全トレース大量
生成
グループ基準に一致するトレースの集合
サービスグラフグループ専用
トレース要約
CWメトリクス毎分発行
  • グループはフィルタ式で「受け入れるトレースの基準」を定義し、名前またはARNで呼び出すと「独自のサービスグラフ、トレース要約、CloudWatchメトリクス」を生成できる("generate its own service graph, trace summaries, and Amazon CloudWatch metrics")
  • 「各基準に一致するトレース数のメトリクスは、CloudWatchに毎分発行される」("Metrics for the number of traces matching each criteria are published to CloudWatch every minute")
  • サービスグラフのデータ保持は30日("Service graph data is retained for 30 days")。トレースデータも30日
  • 注意: フィルタ式を更新しても既存の記録は変わらず、以後のトレースにのみ適用される(新旧が混ざるのを避けたければグループを作り直す)

フィルタ式で切り出したグループからは、専用の地図に加えてCloudWatchメトリクスが毎分生まれる。前レッスン(logs-to-metrics)がログからメトリクスを生んだのと対をなし、ここではトレースからメトリクスが生まれる——ミクロの観測を集計してマクロの指標を復元する、同じ統計の発想が繰り返される。

公式ドキュメントで詳しく ↗