ストリーム優先度

優先度 (HTTP)

[55] HTTP/2 ストリームは、優先度 (priority) を持ちます。 複数のメッセージの送受信は、優先度を参考に順序が決定されます。

仕様書

意味

[5] エンドポイントは、各ストリームについて、 peer が当該ストリーム資源を割り当てる際に (他のストリームに対して) どの程度優先するべきかを指定できます。 >>2

[6] エンドポイントは、 (送信能力が限られる時に) 送信するストリームを選ぶに当たり、 優先度を使うことができます。 >>2

[57] 優先度の指定は、 peer に対するヒントに過ぎません。 その値によって他のストリームに対する転送処理の順序が保証されるわけではありません >>2。 具体的な順序の決定方法も規定されていません。

[47] なお優先度の使い方は、fingerprinting vector です >>46

[8] 優先度は、依存性木により決まります。

依存性

[12] あるストリームから他のストリームへの依存性 (dependency) を指定することができます。 依存性関係において、 依存している方のストリーム依存ストリーム (dependent stream) 、 依存されている方のストリーム親ストリーム (parent stream) といいます >>12

[56] ストリーム親ストリームは、1つです。 ストリーム依存ストリームは、0個以上の任意の個数存在できます。 従って依存性関係は、ストリーム節点とするになります。 これを依存性木 (dependency tree) といいます。

[15] 同じ親ストリームを持つ依存ストリームは、 互いに順序を持ちません。 >>2

[20] 依存ストリームには、 1 以上 256 以下整数重み (weight) が割り当てられます >>2

[60] 重みは、依存性木における重みと考えることができます。

[61] なお、節点としては通常のストリームの他に、ストリーム識別子 0x0 の (ダミーの) ストリームを使います >>2

[62] 他の方法で依存性が設定されなかったストリームは、この特別なストリーム依存ストリームとなります。 従って依存性木は、接続中のすべてのストリームを含む唯一のになります。

依存性の指定

[10] HEADERS フレームPRIORITY フレームを使って、依存ストリーム重みを明示的に指定できます。

依存性
親ストリーム
ストリーム識別子欄に示されたストリーム
依存ストリーム
payloadストリーム依存性欄に示されたストリーム
重み
payload重み欄の値

[3] その場合の変更操作は、次のようにします。

  1. [18]依存ストリームと新親ストリームが同じなら、 ストリームエラー PROTOCOL_ERROR としなければなりません >>2。 停止します。
  2. [19]依存ストリームが新親ストリーム依存性木上の祖先なら、
    1. [9]依存ストリームの各依存ストリームについて、
      1. [13] 親ストリームを、新依存ストリームの現在の親ストリームに設定します。 重みは変更しません。 >>2
  3. [14] 排他的 (exclusive) フラグが設定されていれば、
    1. [63]親ストリームの各依存ストリームについて、それが新依存ストリームでなければ、
      1. [16] 親ストリームを、新依存ストリームに設定します >>2
  4. [4] 依存ストリーム親ストリームを、新親ストリームに設定します。 新しい重みを設定します。

[7] 変更操作は、新依存ストリーム依存ストリームには影響しません。 従って新依存ストリームと共に上の位置が移動することになります >>2
[72] この操作をフレーム処理のどの段階で行うべきなのかは定かではありません。 ヘッダーのエラー検査やストリームの状態遷移の処理の後が妥当でしょうか。

[70] HEADERS フレームPRIORITY (0x20 = 第5ビット) フラグは、 設定されていれば、排他的 (E) フラグ、ストリーム依存性欄、重み欄が存在することを表します。 >>66 設定されていなければこれらの欄は存在しません。

[67] HEADERS フレームPRIORITY フレームE (排他的 (Exclusive) ) フラグは、 ストリーム依存性排他的かどうかを表す1ビットのフラグです >>66, >>34

[68] HEADERS フレームPRIORITY フレームストリーム依存性 (Stream Dependency) 欄は、 ストリームが依存するストリームストリーム識別子を表す31ビットの欄 (ネットワークバイト順 >>50) です。 >>66, >>34

[71] 存在しないストリームが指定された時、受信者がどうするべきなのかは定かではありません。 idle 状態も含め、適切なストリームを表していれば、それについて依存性を設定するべきでしょう。 peer が開始するべきストリームが指定された時どうするべきなのかは不明です。 ChromeFirefox も、そのような指定を受信してもエラーとはしません。

クライアントが優先度の指定を受信してもエラーにならなければ挙動が変化しないようなので、 どう扱っているのか観測できません。

[69] HEADERS フレームPRIORITY フレーム重み (Weight) 欄は、 ストリーム優先度重みを表す符号無し8ビット整数です。 重みは 1 以上 256 以下で、ここで指定するのはそれより 1 小さい値です。 >>66, >>34

[33] PUSH_PROMISE フレームによって予約されたストリームは、 元のストリームに依存します >>2

依存性
親ストリーム
ストリーム識別子欄に示されたストリーム
依存ストリーム
payload約束ストリーム識別子欄に示されたストリーム
重み
既定値 (16) >>2

[11] 他のストリームへの依存性が指定されていなければ、 ストリーム 0x0 に依存することとします >>2

依存性
親ストリーム
0x0
依存ストリーム
ストリーム
重み
既定値 (16) >>2

[49] Upgrade: h2c により作成されるストリーム識別子 1ストリームも、既定値となります >>48

ストリームの削除

[64] エンドポイントは、ストリームの情報を依存性木から削除することも認められています。

[22] その場合、削除ストリーム依存ストリームは、 削除ストリーム親ストリーム依存ストリームとなります。 依存性重みは、削除されるストリーム重みを各依存ストリーム重みで分配した値とします。 >>2

[23] これによって優先度の情報はいくらか失われることになります。 例えばあるストリーム依存ストリーム間で資源を共有していた状態でそのいずれかの依存ストリームが閉じられると、 開いた資源はその親ストリームの他の依存ストリームに割り当てられることになります。 しかし親ストリームが変わっていると違った形で再分配されることになります。 >>2

[24] 依存性で指定されたストリーム優先度が関連付けられていない場合は、 既定優先度 (重み 16) を割り当てます >>2

[25] これは意図とは異なるかもしれませんから、好ましくない優先度付けとなるかもしれません >>2

[26] これらの問題を防ぐため、閉じたストリーム優先度の状態を一定期間保持し続けるべきです>>2

[27] idleclosed の状態のストリームにも優先度を割り当てたり他のストリーム親ストリームとしたりできますから、 これを依存性の中でストリームをまとめる節点を作り、 優先度を柔軟に表現するために使うことができます。 >>2, >>34

[28] こうした SETTINGS_MAX_CONCURRENT_STREAMS 制限に含まれないストリーム優先度情報を多数保持するのは大変かもしれませんから、 優先度を保持する量は制限しても構いません。保持する量は負荷に依存するかもしれません。 >>2

[29] 極端な場合には、活性のストリームや予約されているストリーム優先度も捨てることもできます。 >>2

[30] しかし制限する場合、最低でも SETTINGS_MAX_CONCURRENT_STREAMS 分のストリームの状態は保持するべきです >>2

[31] 活性のストリームの状態は、保持するよう試みるべきです >>2

[65] closed 状態以外のストリームで (他の送受信操作は通常通り行うのに) 優先度の情報は削除せざるを得ない状況が存在するのかは謎です。 SHOULD ではなくて MUST で良い気がしますが......

[32] 閉じたストリーム優先度を保持している場合は、 PRIORITY フレームを受信したら、 依存ストリーム優先度を変更するべきです >>2

資源の割り当て

[17] 依存性木における依存ストリームには、 その親ストリーム祖先のすべてが閉じられるか、 それ以上の進捗ができなくなったかの場合に限り、 資源を割り当てるべきです >>2

[21] 同じ親ストリームを持つストリームには、 重みの比率によって資源を割り当てるべきです >>2

[74] 依存性木サーバーの処理順序の指定として用いられることが想定されているようです。 プロトコル上はサーバーも優先度を指定できますが、クライアントがそれをどう利用するか (しないか) は明らかではありません。

PRIORITY フレーム

意味

[35] PRIORITY フレーム (フレーム型 0x2) は、ストリーム優先度について送信者ヒントを示すものです。 >>34

構文

[42] 常にストリーム識別子を指定しなければなりません >>340x0 を指定することはできません。

[41] フラグはありません >>34。0 でなければなりません >>51受信者は無視しなければなりません >>51

width
8
  1. 1 0
  2. 1 0
  3. 1 0
  4. 1 0
  5. 1 0
  6. 1 0
  7. 1 0
  8. 1 0

[37] payload は次の欄で構成されます。

[38] E
ストリーム依存性排他的かどうかを示す1ビットのフラグです >>34
[39] ストリーム依存性 (stream dependency)
このストリームが依存するストリームを表す31ビットストリーム識別子 (ネットワークバイト順 >>50) です >>34
[40] 重み (weight)
ストリーム優先度重みを表す符号無し8ビット整数です。 1 以上 256 以下の値から1引いたものです。 >>34

width
32
  1. 1 E
  2. 31 ストリーム依存性
  3. 8 重み

文脈

[36] idleclosed を含め、任意の状態のストリームで送信できます >>34, >>52

[44] ただし header block 送信の途中には送信できません >>34

処理

[43] 受信者は、ストリーム識別子0x0 なら、 接続エラー PROTOCOL_ERROR としなければなりません >>34

[45] 受信者は、payload の長さが 5 以外なら、 ストリームエラー FRAME_SIZE_ERROR としなければなりません >>34

[73] ストリームの状態遷移の項も参照。

[75] ChromeFirefox も、 HEADERS または PUSH_PROMISE より先に PRIORITY を受信すると (RFC 的には open 状態で受け入れられるはずですが) 接続エラー PROTOCOL_ERROR とします。

[53] half-closed (local) でも受信するかもしれません >>52依存ストリーム優先度の設定に使われます >>52

[54] closed でも受信するかもしれません。処理するべきです。 しかし依存性木から削除した後なら、無視できます。 >>52

[58] PRIORITY フレームは、無駄な処理をさせるために濫用できます。 エンドポイントは利用状況を監視して制限するべきです接続エラー ENHANCE_YOUR_CALM としても構いません。 >>59

歴史

[77] Fold request type into destination (annevk著, ) <https://github.com/whatwg/fetch/commit/d7052e2b6d24d04caa2cea8ef664923ecdb1e35c>

[78] APNs Provider API () <https://developer.apple.com/jp/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html>

APNsはHTTP/2 PRIORITYフレームを無視するので、ストリーム上でこれを送信することはできません。

[79] Copy priority for service worker passthrough requests (jakearchibald著, ) <https://github.com/whatwg/fetch/commit/b281c58a6dde6c36fd18d62d2b05e3899cd6d595>

[80] Copy priority so service worker pass-through requests don't lose it by jakearchibald · Pull Request #785 · whatwg/fetch () <https://github.com/whatwg/fetch/pull/785>