代表的な面接トピック

HTTP/3のGOAWAYはどのようにして観測可能なグレースフルシャットダウンを実現するのか?

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

質問

受け入れ済みのリクエストを中断せず、非冪等な送信の重複も発生させずにHTTP/3ゲートウェイをローリングアップデートしようとしています。GOAWAYのセマンティクス、サーバーのドレイン順序、クライアントのリトライ、および検証メトリクスについて説明してください。

プロンプトとコンテキスト

HTTP/3ゲートウェイは、長時間接続と多重化されたリクエストを処理します。ロールアウト中には、新規作業を拒絶し、受け入れ済みリクエストを完了させ、期限後に安全に切断する必要があります。RFC 9114のGOAWAYを用いたグレースフルシャットダウンを設計し、QUICのコネクション切断およびHTTPリトライとの境界を説明してください。

面接官が見ているポイント

今後のリクエストを制限するGOAWAYと、QUIC接続を終了するCONNECTION_CLOSEの違いを区別できているか。HTTP/3のGOAWAYはリクエストストリームIDの上限値を持ちます。サーバーはまず広い値から開始し、最終的な境界へと縮小させることができます。並行ストリーム、未処理リクエストに関するクライアントの認識、冪等性、プロキシの伝播、タイムアウト、そしてオブザーバビリティを網羅してください。

最初に確認すべき明確化のための質問

リクエストと接続の特性

ロングポーリング、アップロード、WebTransport、非冪等なPOST、リバースプロキシの有無について質問します。完了時間やリトライのリスクはストリームのタイプによって異なります。

ドレインの目的と期限

これが接続のドレインなのか、ノードのメンテナンスなのか、障害の隔離なのかを明確にします。最大ドレイン期限、ハードクローズ期限、およびロールアウトのバッチサイズを設定します。そうしないと、古い接続が無期限にキャパシティを消費し続ける可能性があります。

クライアントの機能

クライアントやプロキシがGOAWAYを処理し、再接続とマイグレーションをサポートし、「新しいストリームが拒絶された」のか「リクエストは実行されたがレスポンスが失われた」のかを区別できるか確認します。

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

「HTTP/3のGOAWAYはリクエストストリームIDの境界を通知します。これを受信したピアは、その境界を超える新しいリクエストを作成してはなりません。サーバーはまず広い値を送信して新規作業の割り当てを停止し、その後、より小さな最終値を送信することで、どのリクエストが受け入れられなかった可能性があるかをクライアントに伝えます。受け入れられたストリームはドレインされ、期限後にサーバーはQUICのCONNECTION_CLOSEを使用します。クライアントは、リクエストが実行されておらず操作の再試行が安全であると確認できる場合にのみリトライします。」

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

ステップ 1: GOAWAYとCONNECTION_CLOSEを分離する

GOAWAYは最大リクエストストリームIDを制限するHTTP/3の制御メッセージであり、接続を即座に終了するものではありません。CONNECTION_CLOSEはQUICを終了させるため、処理中のリクエストを中断する可能性があります。まずはGOAWAYでドレインを行い、ハード期限に達したときにのみ切断します。

ステップ 2: 広い境界から狭い境界への縮小を使用する

観測された並行リクエストをカバーする大きなIDを送信して新しい作業の受け入れを停止し、その後に小さな最終IDを送信します。クライアントは、この縮小プロセスを新しいリクエストを作成してよい許可と解釈してはなりません。再接続ロジックが決定的になるよう、制御フレームの順序と状態を維持します。

ステップ 3: 受け入れ済み、未開始、および状態不明なリクエストの処理

最終境界より下の受け入れ済みストリームは継続します。それを超えるリクエストは受け入れられていないため、新しい接続でリトライできます。非冪等なリクエストが実行されたかどうかをサーバー側で判断できない場合は、盲目的に再送するのではなく、冪等性キーやステータス照会エンドポイントを提供します。

ステップ 4: プロキシとマイグレーションの動作を設計する

アップストリームのGOAWAYを受信したリバースプロキシは、その接続への新規リクエストの割り当てを停止し、ドレイン状態をダウンストリームに伝播させる必要があります。QUICのコネクションマイグレーションはリクエストのマイグレーションではありません。パスの変更によって実行中のHTTPストリームが安全に移譲されるわけではありません。

ステップ 5: ドレインとハードクローズの期限を設定する

GOAWAYの送信時刻、最後のアクティブストリーム、および残りのリクエストを記録します。ドレインのタイムアウト時には未完了のストリームをキャンセルし、ハードクローズ時にはCONNECTION_CLOSEを送信して接続を解放します。キャパシティが枯渇しないよう、一度にドレインするインスタンス数を制限します。

ステップ 6: リトライと副作用を保護する

リトライは、未実行であることが確認された冪等なメソッド、または冪等性キーを持つ書き込みリクエストに限定し、エクスポネンシャルバックオフとリトライバジェットを適用します。レスポンスの喪失はリクエストが実行されなかったことを証明するものではありません。決済や在庫の更新にはサーバー側の重複排除が必要です。

ステップ 7: ロールアウトを検証する

カナリア環境で、長時間リクエスト、並行ストリーム、再接続、GOAWAY値の縮小、プロキシ伝播、およびハードクローズを注入します。拒絶された新規ストリーム、ドレイン時間、未完了ストリーム、リトライ率、重複した副作用、接続エラー、およびキャパシティのヘッドルームを監視します。ロールアウト全体を通じてp99レイテンシとエラー率を確認します。

質の高い回答例

新規接続の割り当てを停止し、広いGOAWAYを送信して新しいストリームを停止させた後、並行リクエストを観測してからより小さな最終境界を送信します。境界以下の受け入れ済みストリームはドレインされ、期限が切れた後にのみキャンセルされてQUIC接続が閉じられます。クライアントは未実行が確認された冪等な操作のみをリトライし、非冪等な書き込みには冪等性キーを使用します。プロキシはドレイン状態を伝播させ、マイグレーションをリクエストの移譲として扱うことは決してありません。カナリアテストでは長時間リクエスト、並行ストリーム、リトライ、プロキシの挙動、および重複した副作用をカバーします。

よくある間違い

  • 間違い: GOAWAYの直後にQUICを切断する。 → 失敗する理由: アクティブなリクエストが中断される。 → 修正方法: まずドレインを行い、ハード期限で切断する。
  • 間違い: GOAWAYの制限値を実行台帳として扱う。 → 失敗する理由: ストリームIDは範囲を表すものであり、アプリケーションの完了を示すものではない。 → 修正方法: アプリケーションの状態と冪等性キーで確認する。
  • 間違い: 失敗したすべてのリクエストをリトライする。 → 失敗する理由: 副作用が発生した後にレスポンスが失われた可能性がある。 → 修正方法: リトライを冪等またはキー付きの操作に限定する。
  • 間違い: コネクションマイグレーションによってアクティブなリクエストが移譲されると思い込む。 → 失敗する理由: パスが変更されてもHTTPストリームの状態は変わらない。 → 修正方法: 安全なリトライには新しい接続を使用する。

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

フォローアップ 1: なぜGOAWAYの値は縮小できるのか?

サーバーはまず観測された並行リクエストをカバーし、その後に新しいストリームに対する最終的な境界を確定できるためです。値を縮小できるようにすることで、クライアントは最初のシグナルですべての処理中リクエストを推測することなく収束できます。

フォローアップ 2: クライアントはリクエストが受け入れられたかどうかをどうやって知るのか?

ストリームIDを最終境界と比較することで可能な範囲を特定できますが、アプリケーションコードが実行されたかどうかまでは分かりません。レスポンス、接続エラー、および冪等性ステータスの照会を組み合わせて判断します。

フォローアップ 3: GOAWAYはプロキシ経由で自動的に伝播されるのか?

自動的に伝播されると想定してはなりません。プロキシは独立したHTTP/3エンドポイントであり、アップストリームのドレインをダウンストリームの接続およびルーティングポリシーに変換する必要があります。

フォローアップ 4: なぜハードクローズの前にストリームをキャンセルするのか?

キャンセルによってアプリケーションリソースが解放され、明確な理由が記録されるため、クライアントはドレインのタイムアウトとネットワーク障害を区別できます。QUICのクローズは接続の最終的な境界であり、アプリケーションのクリーンアップメカニズムではありません。

公開情報ソース

関連する質問