代表的な面接トピック

バックエンド面接:WebSockets を HTTP/2 Extended CONNECT 上でどのように実行しますか?

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

質問

ゲートウェイは HTTP/2 に標準化されていますが、リアルタイムサービスは依然として HTTP/1.1 Upgrade を使用しています。プロキシのサポート、ストリームのクローズ、フォールバック、可観測性を考慮しながら、Extended CONNECT へどのように移行しますか?

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

ゲートウェイとクライアントが HTTP/2 をサポートしており、リアルタイムサービスが 1 つの接続上で WebSocket ストリームを多重化したいと考えています。ハンドシェイク、機能ネゴシエーション、プロキシ互換性、ストリームと接続の切断分離、フォールバック、受け入れメトリクスを含む RFC 8441 移行を設計してください。これは HTTP/2 extended-connect セマンティクスに関する backend の質問です。

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

  1. Extended CONNECT と HTTP/1.1 Upgrade の違いを明確に区別できているか。
  2. :protocol および SETTINGS_ENABLE_CONNECT_PROTOCOL を正しく使用できているか。
  3. HTTP/2 ストリームのクローズと接続のクローズを分離して扱えているか。
  4. サポートされていないプロキシやクライアント向けのフォールバックを設計できているか。
  5. ハンドシェイク、ストリームエラー、接続再利用、レイテンシを測定できているか。

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

  • クライアント、エッジプロキシ、ロードバランサー、ゲートウェイ、オリジンは RFC 8441 をサポートしていますか?
  • 通常のリクエストと WebSocket ストリームは 1 つの HTTP/2 接続を共有できますか?
  • ロードバランサーは HTTP/2 をエンドツーエンドで維持しますか、それとも一度終端して再構築しますか?
  • レガシーなクライアントは HTTP/1.1 Upgrade を引き続き使用できますか?
  • クライアントはブラウザ、ネイティブ SDK、それとも社内 RPC 実装ですか?

30秒での回答

「すべてのホップで SETTINGS_ENABLE_CONNECT_PROTOCOL を検証します。対応クライアントは :protocol = websocket を付加した Extended CONNECT を送信し、成功するとその HTTP/2 ストリーム上で WebSocket フレームが転送されます。非対応のホップでは HTTP/1.1 Upgrade にフォールバックします。1 つのストリームのキャンセルが接続全体を閉じてはなりません。カナリアリリース期間中は、ハンドシェイク成功率、フォールバック、RST_STREAM、GOAWAY、再利用率、初回メッセージのレイテンシを追跡します。」

詳細解説

ステップ 1: 拡張機能サポートのネゴシエーション

エンドポイントは HTTP/2 SETTINGS を介して Extended CONNECT を通知します。クライアントはサポートを確認した後にのみ :protocol 疑似ヘッダーを送信します。この設定を削除するプロキシが存在する場合、無効なリクエストを送信するのではなくフォールバックをトリガーする必要があります。

text
SETTINGS_ENABLE_CONNECT_PROTOCOL = 1
:method = CONNECT
:protocol = websocket
:authority = chat.example

このスニペットはハンドシェイクフィールドを示しています。フレーム順序は引き続き HTTP/2 および RFC 8441 に従います。

ステップ 2: ハンドシェイクとストリームデータの処理

Extended CONNECT に成功すると、WebSocket フレームセマンティクスを伝送する HTTP/2 ストリームが作成されます。HTTP/1.1 の ConnectionUpgradeSec-WebSocket-Key、または 101 パスは使用されません。サーバーは引き続き認証、オリジン検証、サブプロトコルや拡張機能のネゴシエーションを実施します。

ステップ 3: ライフサイクルの分離

RST_STREAM または通常のストリームクローズは対象の WebSocket にのみ影響し、接続上の他のリクエストには影響しません。GOAWAY は新規ストリームの作成を防止するため、既存のストリームには完了、移行、または再接続のポリシーが必要です。再接続ロジックは、すでに確認応答済みのメッセージが重複して再送信されないようにする必要があります。

ステップ 4: プロキシフォールバックの設計

クライアント、CDN、ロードバランサー、ゲートウェイの機能マトリクスを作成します。いずれかのホップでサポートが欠如している場合は、HTTP/1.1 Upgrade を使用するか、明確な非サポートエラーを返します。:protocol を通常のヘッダーとして転送してはなりません。認証、オリジンチェック、サブプロトコル、ハートビートの動作は両方のパスで一貫性を維持します。

ステップ 5: フロー制御とバックプレッシャー

HTTP/2 のフロー制御ウィンドウとアプリケーションキューの両方が適用されます。ストリームごとおよび接続ごとのバッファを制限し、ウィンドウの停止(stall)を監視して、1 つの低速なストリームが接続を共有する通常のリクエストをブロックしないようにします。

ステップ 6: カナリアリリースとセキュリティチェック

社内クライアントおよび単一リージョンから開始します。ハンドシェイク成功率、初回メッセージレイテンシ、再接続数、RST_STREAM、GOAWAY、プロキシエラーについて Extended CONNECT と HTTP/1.1 Upgrade を比較します。TLS、オリジン、認証、サブプロトコル、メッセージサイズの制限は変更しません。

ステップ 7: ロールバックと受け入れ基準の定義

HTTP/2 WebSockets を無効化できるクライアントレベルまたはリージョンレベルのスイッチを用意します。SETTINGS の欠落、拒否されたプロトコル、ストリームのキャンセル、GOAWAY、ネットワーク変更、重複した再接続をテストします。展開を拡大する前に、メッセージの順序性、p95 レイテンシ、接続数、フォールバック率を比較します。

模範解答

「エンドツーエンドの機能マトリクスを策定し、すべてのホップで SETTINGS_ENABLE_CONNECT_PROTOCOL を必須とします。対応クライアントは :protocol = websocket を含む Extended CONNECT を送信し、接続確立後は HTTP/2 ストリーム上で WebSocket フレームを伝送し、非対応パスでは HTTP/1.1 Upgrade を使用します。認証、オリジン、サブプロトコル、ハートビート、サイズ制限は一貫性を保ちます。

RST_STREAM は対象の単一 WebSocket にのみ影響し、GOAWAY は新規ストリームに影響するため、完了または再接続のポリシーが必要です。カナリアテストでは、SETTINGS の欠落、拒否されたプロトコル、低速ストリーム、ネットワーク変化などの障害を注入しながら、ハンドシェイク、フォールバック、再接続、初回メッセージの p95、再利用率、プロキシエラーを測定します。」

よくある間違い

  • Extended CONNECT を通常のヘッダーとして扱う → プロキシが拒否または誤ルーティングする可能性がある → SETTINGS と疑似ヘッダーを検証する。
  • HTTP/1.1 Upgrade ヘッダーを送信する → HTTP/2 はそのハンドシェイクを使用しない → RFC 8441 に従う。
  • RST_STREAM 時に接続を閉じる → 無関係なリクエストが失敗する → ストリームと接続の状態を分離する。
  • GOAWAY を無視する → 再接続と完了の動作が曖昧になる → ライフサイクルポリシーを定義する。
  • 直接接続のみをテストする → CDN やロードバランサーの差異により本番環境で障害が発生する → すべてのホップをテストする。
  • 移行中に認証を脱落させる → この拡張機能によって WebSocket のセキュリティ要件が変わることはない → 既存のポリシーを再利用する。

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

フォローアップ 1: なぜ HTTP/3 WebSockets を直接使用しないのですか?

RFC 9220 が HTTP/3 パスを定義しています。既存のエンドツーエンドインフラが HTTP/2 である場合、RFC 8441 が現実的なステップとなります。サポート状況と移行コストによって判断します。

フォローアップ 2: クライアントは設定なしで Extended CONNECT を試行できますか?

できません。プロトコル上無効なリクエストを送信するのではなく、機能シグナルを待機してからフォールバックするか、非サポートを報告する必要があります。

フォローアップ 3: GOAWAY 後のメッセージ重複をどのように防ぎますか?

クライアントのシーケンス番号または冪等性キーを使用し、確認応答済みのオフセットを永続化して、再接続後に確定したポイントから再開します。

フォローアップ 4: 互換性のないプロキシをどのように特定しますか?

プロキシ、リージョン、クライアントバージョンごとに分割し、SETTINGS、CONNECT レスポンス、エラーコードをホップ単位でキャプチャします。

公開情報ソース

関連する質問