代表的な面接トピック

バックエンド面接:非同期メッセージ間でトレースコンテキストをどのように伝播させますか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

HTTPリクエストが非同期処理のためにメッセージを発行します。リトライ、バッチ処理、マルチテナントにまたがって、トレースコンテキストを安全に伝播させるにはどうすればよいですか?

プロンプトとユースケース

HTTPリクエストが非同期処理のためにメッセージを発行します。リトライ、バッチ処理、マルチテナントにまたがって、トレースコンテキストを安全に伝播させるにはどうすればよいですか?このプロンプトは、バックエンド、オブザーバビリティ、およびメッセージングに関する面接に適しています。目的は、リクエストコンテキストを恒久的な認可やビジネスデータとして扱うことなく、実行境界を越えた因果関係の相関を実現することです。

面接官が評価するポイント

  • traceparent、任意のtracestate、およびプロパゲーターの境界を理解しているか。
  • プロデューサー、メッセージ処理、リトライの各スパンに明確な親子関係があるか。
  • バッチメッセージ、遅延消費、デッドレター、サンプリング、有効期限を適切に処理できるか。
  • 機密性の高いバゲッジ、テナント間データ、偽造された信頼シグナルの拡散を防げるか。

回答前に確認すべき質問

トランスポート、メッセージの耐久性、バッチ処理およびリトライの挙動、コンシューマーがサービスや信頼境界を越えるかどうかを確認します。求められている関係性が、単一のビジネスオペレーション、単一のメッセージ、またはバッチのどれに対するものかを明確にします。サンプリング、保持期間、テナント分離、および外部プロデューサーがコンテキストを注入できるかどうかについて尋ねます。最後に、デッドレター処理と、手動リプレイによって新しいトレースブランチが作成されるかどうかを定義します。

30秒の回答フレームワーク

「エントリサービスは伝播ヘッダーを抽出・検証し、メッセージ発行時に最小限のトレースコンテキストを注入します。コンシューマーはそれを抽出し、独立したコンシューマースパンを作成して、リトライ、バッチ、デッドレターを明示的に表現します。信頼境界を越える際は、制御されたフィールドのみを受け入れ、機密性の高いバゲッジを破棄します。サンプリングと有効期限はプラットフォームポリシーによって管理され、リプレイではオリジナルにリンクされた新しいトレースIDを使用します。」

ステップごとの詳細な回答

  1. 境界の定義: HTTPイングレス、メッセージ発行、トランスポート、消費を、明示的な注入(inject)および抽出(extract)の担当を持つ個別の実行ユニットとしてモデル化します。
  2. キャリアの選択: 標準の伝播フォーマットをメッセージヘッダーまたは制御されたメタデータに配置します。リクエスト全体、アイデンティティトークン、任意のバゲッジを耐久性のあるメッセージにコピーしてはなりません。
  3. スパンのモデル化: パブリッシャーはプロデューサースパンを作成し、コンシューマーはコンシューマースパンを作成します。バッチの場合は、バッチ全体を1つのリクエストであるかのように見せかけるのではなく、メッセージリンクを記録します。
  4. リトライとデッドレターの処理: 元のイベントリンクを保持したまま、各試行に独自のスパンと試行属性を付与します。デッドレター処理とリプレイは新しいブランチを作成します。
  5. セキュリティの統制: クロスドメインでの注入を制限し、ユーザー制御フィールドをサニタイズし、テナントラベルを分離し、サンプリング、保持期間、コンテキストサイズを制限します。

質の高い回答例

私なら、標準コンテキスト、ビジネスの相関関係、セキュリティ境界を分離します。HTTPエントリポイントは、適切な形式の伝播ヘッダーのみを抽出し、バージョンと長さを検証してサーバースパンを作成します。発行時、プロデューサースパンは最小限のトレースコンテキストをメッセージメタデータに注入する一方、不変のビジネスイベントIDは別個の目的を持つため個別に保存されます。コンシューマーはメタデータを抽出してコンシューマースパンを作成し、各ダウンストリームオペレーションはそれぞれの子スパンを取得します。バッチは最初のメッセージの下に単一の親として強制されることはありません。バッチスパンと範囲が制限されたメッセージリンクを記録します。すべてのリトライは、イベントIDを保持しながら、試行回数とバックオフ属性を追加します。メッセージがデッドレターキューに入ると、手動リプレイは元のトレースにリンクされた新しいトレースを作成し、新しい実行が過去の履歴に偽装できないようにします。別のテナントや外部プロデューサーからのバゲッジはデフォルトで破棄され、プラットフォームで承認された機密性の低いフィールドのみが境界を通過します。テストと本番メトリクスを使用して、コンテキストサイズ、抽出失敗、メッセージとコンシューマーの相関、リトライの可視性、テナント間の漏洩を検証します。

よくある間違い

  • トレースIDを認証クレデンシャルやビジネスの冪等性キーとして扱うこと。
  • 完全なHTTPヘッダー、ユーザー入力、またはトークンを耐久性のあるメッセージに永続化すること。
  • バッチ消費とすべてのリトライを1つのスパンの下にまとめ、タイミングを歪めること。
  • デッドレターのリプレイ中に古いトレースを再利用し、新しい試行を隠してしまうこと。
  • 信頼ドメイン、サンプリング、保持期間、サイズ統制を考慮せずにSDKの呼び出しのみを議論すること。

フォローアップ質問と回答

メッセージが10回リトライされた場合、スパンはいくつ存在すべきですか?

実際の処理試行ごとに識別可能なスパンを作成し、試行番号、イベントID、および元のプロデューサー操作とリンクさせます。これにより、10回の実行を1回として報告することなく、試行ごとのレイテンシーが明らかになります。

バッチの親はどのように選択しますか?

バッチ用のコンシューマースパンを作成し、分析が必要なメッセージに対しては制限付きのリンクまたは子スパンを使用します。最初のメッセージをバッチの親として恣意的に選択しないでください。サンプリングが制限されている場合は、バッチレベルの統計と相関IDを保持します。

外部の顧客がtracestateを注入することは可能ですか?

プロトコルに準拠したフィールドのみを信頼できない入力として受け入れます。信頼境界を越える場合は、長さ、キー、転送を制限し、機密性の高いフィールドやカーディナリティの高いフィールドを削除し、それらを認可に使用してはなりません。

手動デッドレターリプレイの追跡可能性はどのように維持されますか?

リプレイ用に新しいトレースと実行スパンを作成し、元のメッセージID、オペレーター、理由、およびリプレイバッチを記録します。不変である元の障害を保持しながら、制御された関係を通じて古いトレースと新しいトレースをリンクします。

公開情報ソース

関連する質問