代表的な面接トピック

システムデザイン面接:シャドートラフィック検証システムをどのように設計するか?

システム設計難しい
Offer.cc 編集チーム公開日 更新日

質問

あるチームが、トラフィックを移行する前に実際の運用リクエストに対して新しいバックエンドを検証したいと考えています。リクエストをミラーリングし、認証情報や副作用を保護し、レスポンスを比較し、リプレイを制御し、新バージョンが安全かどうかをどのように判断しますか?

プロンプトとスコープ

毎秒 20,000 リクエストを受信するサービス向けのシャドートラフィックシステムを設計します。プライマリリクエストは既存の p99 レイテンシーを維持する必要があり、シャドウバージョンは遅延しても構いません。システムはエンドポイントごとにサンプリングを行い、不一致を再現するのに十分な証拠を永続化し、意味のあるレスポンスフィールドを比較し、ミラーリングされたリクエストが決済、メール、その他の外部への副作用を決して送信しないようにする必要があります。

核心となる違いは、パケットキャプチャではなく「リクエストミラーリング」である点です。ロードバランサーは fire-and-forget(投げっぱなし)のコピーをミラーバックエンドに転送でき、プライマリレスポンスが正式なものとして残ります。ネットワークパケットミラーリングはターゲットやカプセル化が異なるため、アプリケーション層を認識するリプレイパスの代替にはなりません。

面接官がテストしていること

面接官が求めているのは、トラフィックをコピーした単なる第2の本番サービスではなく、安全な比較用ハーネスです。優れた回答は、プライマリのレイテンシーパスを保護し、認証情報を削除し、書き込みを隔離し、サンプリングを再現可能にし、バイト単位の単純な差分比較がなぜ不適切であることが多いのかを説明します。

面接官は、キャプチャキューがいっぱいになったとき、シャドウの処理が遅いとき、レスポンスにタイムスタンプが含まれるとき、プライマリがすでに書き込みを実行したときに何が起こるかを掘り下げてきます。これらの一つひとつを明示的なポリシーとして扱ってください。

設計を左右する確認事項

  • リクエストは読み取り専用ですか? 読み取り専用リクエストは直接リプレイできます。変更を伴うリクエストにはサンドボックス、スタブ、または合成ID(synthetic identity)が必要です。
  • 比較は完全一致ですか、それともセマンティック(意味的)ですか? 完全一致は決定論的な JSON に適しています。マスクや不変条件(invariant)チェックは、タイムスタンプや自動生成 ID に適しています。
  • キャプチャされたボディに個人データが含まれる可能性はありますか? 含まれる場合は、保存前に墨消し(マスキング)し、参照を暗号化し、保持期間とアクセス監査を定義します。
  • 目的は移行の正確性、レイテンシー、それともキャパシティですか? 目的によってメトリクスとサンプリングポリシーが変わります。

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

「認証・認可の完了後、外部への書き込みが発生する前に認証済みリクエストをキャプチャし、シークレットと個人データをサニタイズして、決定論的なサンプルを非同期にエンキューします。プライマリレスポンスが常に正式なものとなります。隔離されたシャドウワーカーが、レート制限と独立した認証情報を用いてサンドボックスに対してリプレイします。差分比較サービスは、事前に宣言された非決定論的要素を無視しながら、ステータス、選択されたフィールド、不変条件、レイテンシーを比較します。耐久性のあるキャプチャにより調査が可能になりますが、キューが溢れた場合はユーザーの処理を遅らせるのではなくミラー側をドロップします。昇格(プロモーション)には、定義された乖離率およびエラーバジェットに加え、書き込み、プライバシー、シャドウのキャパシティが安全であることの確認が必要です。」

ステップごとの設計

1. クリティカルパスに影響を与えずにキャプチャする

認証および認可の後にキャプチャフックを配置し、システムがエンドポイントとテナントポリシーを把握できるようにしつつ、元に戻せない外部呼び出しが行われる前に配置します。シャドウに必要なフィールドのみをコピーします。認可ヘッダー、Cookie、ユーザートークン、決済情報を削除し、存続期間の短いシャドウ用認証情報または固定のテスト用アイデンティティに置き換えます。

リクエスト ID、トレース ID、エンドポイント、サニタイズされたヘッダー、ボディ参照、キャプチャ時刻、ターゲットバージョン、サンプリング構成バージョンを含む MirroredRequest を発行します。エンキュー操作には制限時間を設ける必要があります。ローカルバッファまたは永続キューがいっぱいの場合は、ドロップメトリクスを記録し、プライマリレスポンスを返します。

2. サンプリングを再現可能にする

安定したリクエスト ID またはトレース ID をハッシュ化し、設定されたサンプルレートと比較します。これにより、リトライや調査を決定論的に保ちます。エンドポイントおよびテナントごとに2つ目のトークンバケットを適用してミラー RPS を制限します。パーセンテージとトークンバジェットの低い方が優先されます。

すべてのキャプチャにサンプリング構成バージョンを保持します。これにより、後続のレポートで、実際の乖離とサンプリングルールの変更による違いを区別できます。

3. 隔離された環境でのリプレイ

ワーカーは永続キューを読み取り、短いタイムアウトでシャドウターゲットを呼び出します。シャドウは個別のデータベースまたはトランザクションなしのフィクスチャを使用し、決済およびメールプロバイダーをスタブ化し、外部へのアウトバウンドコールバックを無効にする必要があります。読み取りパスの場合、本番ストレージよりも読み取り専用レプリカまたはサニタイズされたスナップショットの方が通常は安全です。

リプレイはリクエスト ID でタグ付けされているため、キャプチャキューにおける at-least-once(少なくとも1回)の配信は許容されます。ワーカーは SHADOW_ERRORDROPPED、または COMPLETED を記録します。シャドウのタイムアウトによって無期限にリトライしたり、プライマリをブロックしたりしてはなりません。

4. 意味に基づいてレスポンスを比較する

まずステータスコードを比較します。成功した JSON レスポンスについては、非決定論的であると明示的に宣言されたフィールドを削除した上で、選択したパスまたは正規化されたボディのハッシュを比較します。「合計が非負である」や「返されたユーザーがリクエストされたテナントに属している」などのドメイン不変条件を追加します。レイテンシーは個別に比較します。レスポンスが正しくても、昇格させるには遅すぎる場合があるためです。

両方のハッシュ、差分パス、プライマリおよびシャドウのレイテンシー、デプロイバージョン、サンプルのリクエスト参照を保存します。レポートに生の機微なボディを保存してはなりません。

5. 昇格ゲートを定義する

リプレイを開始する前に、乖離率、シャドウエラー率、レイテンシー悪化、キューの滞留時間、マスキング失敗などのしきい値を設定します。エンドポイント、テナントティア、リージョン、レスポンスクラスごとにレポートをセグメント化します。全体の集計がグリーンであっても、決済エンドポイントの破損が隠れてしまう可能性があるためです。

最小サンプル数を設定したスライディングウィンドウを使用します。1% の乖離しきい値はポリシーの例であり、普遍的なルールではありません。昇格には、安全でない副作用がゼロであること、シャドウのキャパシティが許容範囲内であること、および重大度の高い差分のすべてについてサンプルがレビューされていることも求められます。

6. 運用とリカバリ

シャドウが過負荷になったときは、キャプチャを無効にすることなくリプレイを一時停止します。プライバシーポリシーに従ってキャプチャを期限切れにし、保存されているリクエスト参照へのアクセスを監査します。シャドウバージョンがロールバックされた場合、後の分析でバージョンが混同されないよう、レポートをデプロイメントに紐づけて保持します。

キューの消失、重複キャプチャ、古い構成、認証情報の漏洩、副作用の試行、非決定論的フィールド、シャドウのタイムアウト、リージョン障害をテストします。成功の基準は、シャドウが実用的で再現可能な証拠を生成しながら、プライマリサービスがその SLO 内を維持することです。

質の高い模範回答

「認証後かつ外部書き込みの前に、アプリケーションを認識するミラーフックを構築します。これは本番の認証情報と機微なフィールドを削除し、ボディ参照を保存し、トレース ID によって決定論的にサンプリングします。プライマリパスはミラーを待機しません。高負荷時には有界キューによってミラー側の処理をドロップできます。

隔離されたワーカーが、独立したアイデンティティ、データベース、スタブ化されたプロバイダーを持つシャドウバージョンに対してリプレイします。各リプレイにはリクエスト ID とタイムアウトが設定されます。比較サービスは、非決定論的と宣言されたフィールドのみを無視し、ステータス、選択された JSON パス、ドメイン不変条件、およびレイテンシーを検証します。レポートにはハッシュ、差分パス、バージョン、およびサニタイズされたサンプルが保持されます。

昇格させる前に、乖離、エラー、レイテンシー、キュー滞留時間、プライバシー違反についてエンドポイントレベルのゲートを設定し、最小サンプル数を要求し、重大な差分を調査します。変更を伴うエンドポイントはサンドボックスが必要であり、そうでなければ除外します。プライマリの SLO が変化しないことを証明しつつ、キューのオーバーフロー、重複、認証情報の除去、副作用、およびリージョン障害を検証します。」

よくある間違い

  • 間違い → 失敗 → 解決策: 本番の認証情報をリプレイする → シャドウの呼び出しが実システムの情報漏洩やデータ変更を引き起こす → シークレットを削除し、隔離されたアイデンティティとプロバイダーを使用する。
  • 間違い → 失敗 → 解決策: レスポンスを返す前にシャドウを待つ → 移行テストによってユーザーのレイテンシーが増加する → 非同期にエンキューし、高負荷時にはミラー処理をドロップする。
  • 間違い → 失敗 → 解決策: 生のボディのみを比較する → タイムスタンプや生成された ID によって偽陽性(誤検知)が発生する → 正規化を行い、宣言されたフィールドと不変条件を比較する。
  • 間違い → 失敗 → 解決策: すべてのリクエストを永久にミラーリングする → ストレージ、プライバシーリスク、シャドウのキャパシティが無制限に増大する → 決定論的サンプリング、クォータ、データ保持期間、アクセス監査を使用する。
  • 間違い → 失敗 → 解決策: 単一のグローバルな乖離率を使用する → 全体としては正常に見えても、重要な小さなエンドポイントの障害が見落とされる → エンドポイント、テナント、リージョン、重大度ごとにゲートを設定する。

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

エンドポイントがデータベースに書き込みを行う場合はどうしますか?

シャドウを使い捨てのデータベースまたはトランザクションスタブにルーティングし、外部呼び出しを意図を記録するフェイク(擬似実装)に置き換えます。書き込みを隔離できない場合は、結果が安全であるかのように装うのではなく、そのエンドポイントを除外してカバレッジのギャップを明示します。

キャプチャキューがいっぱいになった場合はどうしますか?

プライマリリクエストに対してはフェイルオープンにします。ミラーコピーをドロップし、ラベル付きメトリクスをインクリメントし、ドロップバジェットを超えた場合にアラートを発報します。プライマリにバックプレッシャーをかけると、最も重要な安全性特性が損なわれます。

個人を特定できる情報(PII)はどのように扱いますか?

キャプチャ時にフィールドを分類し、永続ストレージへの保存前にマスキングまたはトークン化し、ボディ参照を暗号化し、保持期間を制限してアクセスを監査します。機微なペイロードのハッシュであっても個人を特定できる可能性があるため、自動的に安全であるとは言えません。

パケットミラーリングはアプリケーションミラーリングの代わりになりますか?

いいえ。パケットミラーリングはネットワークトラフィックを分析ターゲットにコピーするのに対し、アプリケーションミラーリングはエンドポイントのセマンティクス、認証情報、テナントポリシー、レスポンスの比較を把握します。ネットワークの検査にはパケットミラーリングを使用し、動作の検証にはアプリケーション層を認識するパスを使用してください。

公開情報ソース

関連する質問

関連面接ツール

システム設計の回答には「回答する」を使用

まず要件を明確にし、スケール、アーキテクチャ、コンポーネント選定、トレードオフの順に進めます。

ツールを見る