HTTP/2でのプライオリティ・プレースホルダの提案仕様

元々はHTTP over QUICでの議論に端を発するが、HTTP over QUICの仕様の著者でもあるMicrosoftのMike Bishop氏から「Priority Placeholders in HTTP/2」という仕様が提案されている。

解説すると長くなるので割りと雑目ですみません

HTTP2のプライオリティ制御

まずHTTP/2のプライオリティ制御について軽く説明する。

HTTP/2ではHTTPリクエストが並列的に送信される。そこで、クライアント側からHTTPリクエストを送る際にその要求の優先度を指定できる。サーバはその優先度を尊重してHTTPレスポンスを返す。

これによって、ページの表示に大事なCSSなどは早く、画像などは後でほしいと言ったことが実現されている。

この優先度では各ストリームにDependencyとWegithが設定される。Dependencyは各ストリームの依存関係(ストリームAが終わってから、ストリームBといった制御)、Weightは各コンテンツを返すのに使用するサーバリソースの比である。

すべてのストリームはストリームID=0もしくは他のどれかのストリームに依存する。つまり、木を構成することになり、Priority Treeと呼ばれる。

f:id:ASnoKaze:20170728010502p:plain
(引用: HTTP/2 Deep Dive: Priority & Server Push // Speaker Deck )

丸がストリームID, 四角がWegith,矢印がDependencyを表します。

上記図に示すとおり、Firefoxではストリーム3, 5, 7, 10をidle状態のまま各ストリームをグループに分けるために使用します。画像群やCSS群といったストリーム毎に一括で優先度処理するような形になっています。

ここでポイントになるのは

  • idle状態のストリームを用いて各ストリームの優先度をグループ化している(idleストリーム自体は以後使用しない)
  • HTTP/2ではcloseしたストリームもPriorityに影響してくる(closeしたストリームに依存するストリームを後から追加できる)

QUICとHTTP/2のプライオリティ

現段階ではQUICでもHTTP/2同様のプライオリティ制御方式を使用します。HTTP/2ではTCPを用いていたため送信した順序どおりに受信され処理されていたため、クライアントとサーバでPriority Treeを同期できました。しかし、QUICでは同一ストリーム上でのみ順番が保証されているため、Priorityフレームはconnection controlストリームで送られる事になっています。

また、一点大事な事として、HTTP over QUICでは各ストリームIDを飛ばすことなく使用しなければなりません。

つまりidleのストリームを用いてストリームの依存をグループ分け出来なくなっている。

Priority Placeholders in HTTP/2

Mike Bishop氏の「Priority Placeholders in HTTP/2」では、Priority Tree内でグループ分けをしたい場合は、それ専用のプレースホルダを使用します。このPriority PlaceholdersはSETTINGSフレームで各エンドポイントが合意した場合に使用できます(使用できるプレースホルダ数も合わせて通知されます)。

プレースホルダプレースホルダIDを持っており、新しく追加されたDEPENDENT_ON_PLACEHOLDERフラグがon担っている場合はdependencyの指定がプレースホルダIDという事になります。

プレースホルダの作成はPLACEHOLDER_PRIORITYフレームで作成されます。

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |0|                    Placeholder ID (31)                      |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |0|                  Stream Dependency (31)                     |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |   Weight (8)  |
      +-+-+-+-+-+-+-+-+

Flagやペイロードの意味はPRIORITYフレームとほぼ同等です。

この仕様では、プライオリティ・プレースホルダを使っている場合、サーバはアクティブでないストリームをPriority Treeから削除出来ることになっています(MAY)。詳しいやり方も仕様中に書かれています。

議論

冒頭で述べたように、元々はQUICでのIssueが最初にあり、IETFオフラインミーティングを通して議論されてきており、その結果として今回の提案仕様となった。

議論はML上で続いており「QUICの問題を解決するには、プレースホルダとして「ストリームID」を指定できるように、PRIORITYフレームにフラグを追加してはどうか?」
という話も出ている。