HTTP over QUICと、その名称について (HTTP3について)

2018/11/08 追記
IETF103において、QUIC WGとHTTPbis WGそれぞれでHumが行われ
HTTP over QUICの名称をHTTP/3とするコンセンサスが得られました

QUIC WG

HUMS ON SUPPORTING RENAMING to H3
support hum strongly in favor with non zero do not support. perhaps 70:30
support hum for letting httpbis wg decide: ~100% support

HTTPbis WG

Hum: in favor of HTTP/3.

目次


前回書いたとおり、現在IETFでQUICの標準化がされている
(QUICのトランスポートレイヤについては、下記記事参照)
asnokaze.hatenablog.com

今回はちょうどホットなHTTP over QUICの名称と、概略について雑に書く

HTTP over QUICの名称

Googleが現在使っているQUICとIETFで標準化を行っているQUICはとこどころ異なっており互換性はない。区別して前者をgQUIC、後者をiQUICと呼び分ける。(参照: gQUICのiQUICへの移行について)

実験的なプロトコルであったGoogleのQUICに対して、標準化されたQUICは別の名称をつけるという議論もありましたが、名前を変えずQUICとする方向になっています。

(GoogleのドキュメントではQUICを「Quick UDP Internet Connections」としていますが、IETFのドキュメントではQUICはQUICであり何かの略語ではないとしています)

名前のもう一つの混乱としては、IETFの"QUIC"はトランスポートプロトコルとしての名称であるが、HTTP over QUICを指していると思ってる人がいるところである。IETFで標準化しているQUICはトランスポートプロトコルであり、アプリケーションプロトコルはHTTPに限定されない。

このような混乱を避けるため、QUIC-the-HTTP-bindingに別名をつけQUICから明確に区別できるようにしないかという議論が出ています。

IETF QUIC WG チェアのMark氏より「Identifying our deliverables」というメールがMLに投稿されています。このメールではHTTP/3という名称が提案されています。

これは、現在開催中のIETF103でも議論される予定ですが、HTTP WGとQUIC WGでのコンセンサスが得られればその方向で進む可能性が強くなるでしょう

f:id:ASnoKaze:20181106020504p:plain
(IETF103のQUIC WGのスライドより)

なにかアップデートがあれば更新します。

HTTP over QUIC について

現在の仕様は「Hypertext Transfer Protocol (HTTP) over QUIC」こちら。

さてHTTP/3というと、なにか新しそうなHTTPのような気がしますが、まず基本的なHTTPのセマンティクスに変更はありません。GETやPOSTといったHTTPリクエストがあって、ステータスコードを持つレスポンスが返されます。ただその伝達方法がQUICトランスポートに合わせて改善されています。

個人的な印象としては、HTTP/2に対して下位レイヤとしてQUICトランスポートを使うための変更が入っている感じである。ただし、その変更は多くHTTP/2 over QUICではないという事がわかると思う。

ストリームとフレーム

QUICではトランスポートレイヤにストリームを持つため、HTTP/2であったストリーム管理の多くはなくなっています。例えば各ストリームのフロー制御はなくなっています。QUICレイヤで提供されるストリームをどのように使うかが、HTTP over QUICの仕様では定義されています。それに合わせてHTTP/2で使用していたフレームも一部なくなったり、新しく増えたフレームタイプもあります。それぞれのフレームのフォーマットも変更されています。

HTTP over QUICで定義されるフレームは以下の通り

  • DATA
  • HEADERS
  • PRIORITY
  • CANCEL_PUSH
  • SETTINGS
  • PUSH_PROMISE
  • GOAWAY
  • MAX_PUSH_ID
  • Reserved Frame Types

ストリームの扱いに関しては、通常のHTTPリクエスト/レスポンスは双方向ストリームを使用しますが、SETTINGSなどを送信する制御ストリームやサーバプッシュに使われるプッシュストリームなどは単方向ストリームを使用します。

また、サーバプッシュはPUSH IDと呼ばれる識別子で識別されます。このPUSH IDを用いて、パケットロスを見越して複数回同じプッシュを行うということができます。また、プッシュを中断するためのCANCEL_PUSHフレームや、プッシュ数を制限するMAX_PUSH_IDフレームなどが追加されています。

プライオリティ制御

HTTP over QUICでもHTTP/2のようなストリームに対してWeightとDependencyを設定することで優先度を設定します。

HTTP/2のプライオリティ制御では、ストリームは実際には使用せずプライオリティ制御のためだけに特定のストリームを使用できました。

例えば下記のようなHTTP/2 のdependency treeにおいて、ストリーム3,5,7は各リソースの優先度をグルーピングするためだけに使用されておりました。
f:id:ASnoKaze:20170728010502p:plain

しかし、QUICのストリームは各ストリームタイプでID順に使用していくことになっています。そのため、HTTP/2で行っていたような、実際にはデータの送受信には使用しないストリームをプライオリティ制御のグルーピングのために使用できません。

そのかわりに、HTTP over QUICではPlaceholderというそれ用のIDを用意しておき、そこに対して依存関係を指定するようになっています。また、ストリームID 0は今回はdependency treeのルートではないので明示的にルートしめす値が用意されています。

また、HTTP/2のときにあった問題として、特定のストリームがクローズしていても将来優先度処理で使用される可能性があるのでいつ状態(weight)を破棄していいか分からなかったという点です。HTTP over QUICでは非アクティブなストリームに関する、dependency treeの枝刈りに関する文書が加わり、クライアントは非アクティブなストリームに依存するようなストリームを作成すべきではなくなりました。

QPACK

HTTP/2ではHTTPヘッダ圧縮の仕組みとしてHPACKを使用していました。HTTP over QUICでは、各ストリームの順序が入れ替わる可能性があるため、クライアントが送信したHTTPリクエストの順番の通りにサーバが受信するとは限らなくなりました。この場合、HPACKの動的ヘッダテーブルの更新はクライアントとサーバで状態を正しく動悸することができません。これをそのまま正しく同期しようとおもうと、正しい順番に並び替えるための待ち時間が発生してしまいます。

そこで、HTTP over QUICではQPACKと呼ばれるヘッダ圧縮方式を使用します。この方式では、上記の問題が改善されています。

また、HTTP/2の静的ヘッダテーブルは当時のヘッダ利用状況に基づき作成されましたが、alt-svcヘッダの使用頻度が上がっているなど状況が異なっています。
https://github.com/quicwg/base-drafts/pull/1355 で示されるよう、静的ヘッダテーブルも大きく更新されています。

QUICサーバのディスカバリ

(alt-svcは HTTP over QUIC独自の仕組みではないが)

HTTP over QUICのポートは決められていません。下記の方法でサーバ側からポートも含め指定します。

HTTPレスポンでalt-svcヘッダを用いることで、このオリジンのページを別プロトコル(別サーバ)で提供できることをクライアントにアドバタイズします。
クライアントがHTTP over QUICに対応していればそこに接続してきます。

   Alt-Svc: hq=":50781"

ここで指定する識別子も、名称が変わった場合変更されます。

そのた

その他トランスポートレイヤの変更に伴い、下記の部分について変更が入っている

  • CONNECTメソッドによるトンネリングとエラーについて
  • エラーコード (まちがったストリームタイプの使用など)
  • コネクションの確立と切断