4 分で読了 #networking #HTTP
このページの目次

HTTP/3

HTTP/3 は QUIC 上で HTTP を実行する——TCP に依存せず、UDP でカプセル化し、ストリーム間は完全に独立(ヘッドオブラインブロックなし)。QPACK が HPACK に代わり、0-RTT で接続を再開する。HTTP のセマンティクスは変わらず、トランスポート層が完全に書き換えられた。

概要

HTTP/3(RFC 9114, 2022)は、HTTP を TCP から QUIC(UDP)へ移行し、HTTP/2 の最大の未解決問題であった TCP レベルでのヘッドオブラインブロックを解決しました。1 つのストリームでのパケット損失が他のストリームをブロックすることはなくなりました。QUIC の接続移行機能により、モバイルネットワークの切り替え(WiFi↔4G)でも HTTP 接続が切断されなくなりました。QPACK は HPACK に代わり、ヘッダー圧縮における動的テーブルの HOL ブロックを解決しました。HTTP/3 は HTTP/2 と全く同じセマンティクスを使用しています——トランスポート層が変わっただけです。

HTTP/3 = HTTP/2 セマンティクス + QUIC トランスポート

HTTP/3 は HTTP/2 のすべてのセマンティクス(ストリーム、マルチプレクシング、ヘッダー、メソッド、ステータスコード)を維持しつつ、トランスポート層を置き換えました: TCP → QUIC (UDP)。

主な変更点:

  • ストリーム: TCP バイトストリーム上のフレームマルチプレクシングから、QUIC のストリームはプロトコルの最上位層へ
  • HPACK → QPACK: HPACK の「動的テーブル更新の損失 → HOL ブロック」を解決
  • TLS 1.3: 必須(QUIC は暗号化内蔵、平文の HTTP/3 は存在しない)
  • Server Push: 廃止済み(Chrome/nginx はいずれも削除済み)

QPACK

HPACK の問題: 動的テーブル更新を含む HEADERS フレームが失われると → 受信側は後の HEADERS をデコードできず → HOL ブロックが再発!

QPACK: 動的テーブル更新とデータフレームは、QUIC の異なるユニディレクショナルストリーム上で送信される:

  エンコーダストリーム(ユニディレクショナル、QPACK エンコーダ → デコーダ):
    テーブル更新: Insert (name, value) + TSS (Table State Synchronize)
  
  デコーダストリーム(ユニディレクショナル、デコーダ → エンコーダ):
    フィードバック: Section Acknowledgment, Stream Cancellation

  要求/応答ストリーム(双方向):
    HEADERS + DATA フレーム(動的テーブルのインデックスを参照)

  → テーブル更新の損失はエンコーダストリーム(テーブル更新)のみをブロックし、要求/応答はブロックされない!

デプロイ: Alt-Svc

HTTP/2 または HTTP/1.1 の応答ヘッダー:
  Alt-Svc: h3=":443"; ma=86400

  h3: QUIC 上の HTTP/3
  ma (max-age): 86400 秒間、この代替エンティティを記憶
  :443: QUIC ポート(通常は同じポート)

  ブラウザ: Alt-Svc を受信 → 同じホストへの次回接続で → QUIC:443 を優先して試行
          → QUIC が不通の場合(UDP がブロックされている、QUIC バージョンの不一致)→ TCP にフォールバック

参考

  • RFC: 9114, 9204
  • ツール⁠: curl --http3 -v, Chrome chrome://net-internals/#http3

キーワード: HTTP/3, QUIC, QPACK, Alt-Svc, 接続移行, 0-RTT, ユニディレクショナルストリーム