要約

  • RFC 9218 は、0 が最も急ぎで 7 が最も低い u と、途中の断片にも価値があるかを示す Boolean の i を定義する。初期値は end-to-end の Priority field、後の変更は HTTP/2・HTTP/3 の hop-by-hop PRIORITY_UPDATE で運ばれる。
  • 値は送信者の効用判断であって、帯域、CPU、完了順、再送順の割当ではない。response の Priority も「実行済み」の確認ではなく、intermediary が採用するかどうかを判断する一つの入力にすぎない。
  • 運用で必要なのは、各主張と書き換え、統合規則、接続の共有範囲、queue と flow control、DATA の配分、loss・retransmission、利用者側の到達点を同じ時系列に残すことである。

画面がまだ知らない重要度

記事ページを開くと、ブラウザは head 内のフォントを最初に発見する。ヒーロー画像は responsive source の評価後に決まり、背景の計測要求は script 実行後に出る。初期段階ではフォントが文字表示を止めている。layout が進むと、大きな画像が viewport にあると判明し、進行中の要求を急がせたくなる。

ところがオリジン側では、フォントは多くの edge に保存済みで、画像だけが混雑した shield を通るかもしれない。CDN は一人のページだけでなく、同じ backend pool に集約された別利用者の応答も見ている。ブラウザ、オリジン、CDN は異なる競争集合について話している。

画像が先に終わっても、u=0 が効いたとは限らない。単なる cache hit かもしれない。フォントが先なら、更新が無視されたとも限らない。更新 frame が届く前に bytes が flow-control window に入っていた可能性がある。waterfall は結果を示すが、誰がどの入力で順番を選んだかまでは示さない。

絶対値は絶対的な命令ではない

旧 HTTP/2 の依存木は複雑で、実装間の整合も弱かった。RFC 9218 は Structured Fields Dictionary による小さな絶対値へ移る。request で u がなければ 3、i がなければ false と扱う。i=true は、全部が来る前でも一部を処理できるという性質である。

同じ urgency の non-incremental response は順番に完了させ、incremental response は帯域を分けるのが有益な場合がある。だが、これは “when possible” の助言である。二つの object が同時に u=0 を名乗ったとき、仕様は唯一の先頭を授けない。全要求を最高 urgency にすれば、比較に使える情報がなくなる。

最低の 7 は software update のような background work 向けであり、永久停止の意味ではない。split backend で strict priority を続け、低い stream が全く前進しないと、相手は connection stall と誤認して切断することがある。小さな進捗を全体に配る判断は、local scheduler が負う可用性責任である。

最初の主張と途中の訂正

Priority は request と response の双方に置ける end-to-end field である。client の初期判断を origin まで運び、origin の response 側判断を cache とともに保持できる。HTTP version が変わっても意味を運べる点が強い。

一方、要求後の訂正には PRIORITY_UPDATE を使う。HTTP/2 では 0x10、HTTP/3 では request と push を分ける 0xF0700、0xF0701 が登録されている。frame は現在の hop の peer に完全な Priority Field Value を知らせる。省略した parameter は過去値の維持ではなく default への復帰である。

CDN は client header を保存しながら、backend への hop で別の update を出せる。header 自体を置き換えれば、それ以後の受信者が見る end-to-end statement も変わる。だから一つの “effective priority” だけを記録してはいけない。client view、origin view、各 intermediary の input と output を別々に残す必要がある。

HTTP/3 では control stream の update が対象 request stream より先に届き得る。server は最新値を保持して後で適用できるが、未開通 stream の状態保存は資源を使う。RFC は local limit を認める。priority を送る自由は、受信者に無限の記憶を要求する権利ではない。

Origin は client の採点者ではない

オリジンは、client の見えない内容依存を知ることがある。フォントが全テキストを解放する、ある画像が記事の主証拠である、といった情報を response Priority で示せる。intermediary は request と response を統合できるが、RFC 9218 は唯一の merge algorithm を決めない。

response で parameter がない場合は、その client value を変える意思がないことを示す。request の欠落が default を意味するのとは違う。両方向を同じ正規化処理に通すと、正しい値を消す危険がある。

さらに、response field は acknowledgement ではない。field が返っても scheduler が使った証拠にはならず、返らなくても無視された証拠にはならない。cache から既に配信された、fairness rule が優先された、あるいは transport が詰まった、という別の説明が残る。

Urgency を比較する母集団はホップごとに変わる

edge は多数の client connection を少数の backend に coalesce し、一つの frontend を複数 origin connection に split する。そのたびに競争相手が変わる。u=1 は特定 queue 内の比較値であって、世界全体の順位ではない。

複数 tenant を一つの queue に入れるなら、client scope を証明しなければならない。RFC 9218 は、HTTP/1.1 backend が client priority を使う場合、authentication や session information などで個別 end client に限定できることを求める方向を示す。Priority value 自体には identity がない。

もし誰でも u=0 だけで共有資源を占有できるなら、hint を authorization に変えたのは CDN の設計である。逆に paid tier や background-only connection を意図的に違う扱いにすることもあり得る。その不公平は local policy として owner、尺度、限界を明示すべきで、wire signal の必然として隠してはならない。

QUIC には QUIC の判断材料がある

HTTP scheduler の決定後も、TCP や QUIC が送信可能性を決める。congestion、flow control、loss recovery、pacing が順番を変える。高 urgency の cache miss より低 urgency の hit が速いことも、backend CPU の待ちで header 自体が遅れることもある。

HTTP/3 で packet を失ったとき、低 urgency stream の lost data を再送するか、高 urgency stream の new data を先に出すかは一義的でない。RFC 9218 は transport 実装に universal rule を課さない。回復と応用価値の証拠がその層にしかないからである。

従って causal evidence には、connection/stream ID、raw field と全 update、同時に active だった work、scheduler version と quantum、flow-control/congestion state、時間区間ごとの DATA bytes、loss と retransmission、cache/backend timing、目的とした render milestone が必要になる。

「対応」は六つの動作に分けて確認する

IANA の registry は u と i、HTTP/2 setting 0x9 と frame 0x10、HTTP/3 frame values の衝突を防ぐ。registry にあることは、production peer が negotiation、parse、receipt、scheduling を行った証明ではない。

nghttp2 でも application は旧 priority を使わない setting を送り、extension frame の受信を有効にし、request header または専用 API で update を出す。library に symbol があることと、稼働設定が bytes を変えたことの間には複数の段階がある。

そこで対応証明を六分割する。negotiation、exact parsing、provenance/merge、queue state、byte allocation、controlled contention 下の user outcome である。一つでも推測なら、対応という表現もその範囲に狭めるべきだ。

薄い合意が守るもの

RFC 9218 は Heng Lu の Minimum Initial Specification の好例として読める。共通部分は二つの parameter、dictionary、end-to-end field、version-specific update に絞られる。fairness、cache、backend mapping、transport recovery は Localized Future Decision として実装者に残る。

それは無秩序ではない。選択を観測可能にし、canary で再現し、失敗時に戻せることが条件になる。Voluntary Adoption は文書への賛同ではなく実際の negotiation と behavior で測る。Running-Code Primacy は、主張から queue、bytes、利用者結果までの連鎖を要求する。

その連鎖がなければ、「urgent」は希望であって、次の一バイトに対する権利ではない。

出典