Referene Set とは何だったのか
この記事は HTTP2 Advent Calendar の 8 日目の投稿です。
この記事では、議論の過程で 仕様から外された技術 にフォーカスをあてて、「どういう技術だったのか」と「なぜ仕様から外されたのか」をお伝えします。
間違い等がございましたら、遠慮無くご指摘お願いします。
HPACK と失われし Reference Set
HTTP ヘッダの圧縮仕様は HPACK と呼ばれています。
現在の HPACK 仕様では 3 つの方法でヘッダをエンコードします。
- Literal
- 単なる ASCII エンコード
- Huffman Encode
- 出現頻度の高い文字をより小さいサイズで表現
- 詳しくは 12/16 の Advent Calendar で解説する予定です
- Index
- HTTP ヘッダの key, value を番号で指定する
かつては、上記 3 つに加えて Reference Set という機構が存在していました。
今回の主役は、この Reference Set です。
Reference Set の目的と概要
HTTP/1.1 以前の仕様では、ヘッダの内容に変更が有っても無くても、全てのヘッダを毎回送信しないといけません。
これに対して、Reference Set はヘッダの**「差分情報のみ」を送る**ための仕様です。
具体的には、ヘッダフィールドの追加と削除情報をやり取りします。
では、例を挙げてイメージをつけましょう。
ある時点のリクエストヘッダが「X-Hoge: 1 と X-Fuga: 2」だったとします。
次は「X-Hoge: 1 と X-Piyo: 3」というヘッダとしてリクエストしたいときに、やり取りする内容を表にまとめました。
N 回目 | N + 1 回目 | 差分 | Reference Set 処理 |
---|---|---|---|
X-Hoge: 1 | X-Hoge: 1 | 無し | 何も送信しない |
X-Fuga: 2 | - X-Fuga: 2 | 削除指示を送信 |
| X-Piyo: 3 | + X-Piyo: 3 | 追加指示を送信
この仕様を導入すると、下記のような変更されないヘッダを送信しなくてよいので、通信データを削減できます。
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:34.0) Gecko/20100101 Firefox/34.0
Referer: https://example.com/
また、認証情報は最初 1 回だけ送信すればよいので、セキュリティリスクを低減できる場合があります。
Cookie: authkey=xxxxxxxxxx; sessionid=xxxxxxxxxx
Reference Set に転機が訪れる
導入のメリットがあるにも関わらず、なぜ仕様から外れることになったのでしょうか。それには 2 つの要因があったと思います。
1. データ圧縮への寄与
冒頭で触れた通り、HPACK には Index というエンコード方法があります。
これは、ヘッダの key, value をインデックス (数字) で指定できる機構でした。
もし HPACK に Index 機構が存在しなかったら、Reference Set はまだ仕様に残っていたかもしれません。
というのも、一度インデックスすれば、以降はインデックスの数値を送信すればよく、そのサイズはわずか数バイトです。「Reference Set と Index を両方使った場合」と 「Index のみを使った場合」でデータサイズを比較しても、ヘッダフィールド 1 個あたりわずか数バイトの違いしかありません。
この定量的な評価は @kazu_yamamoto さんが行い、W3C の ML で指摘 されました。
詳細な資料は こちら をご覧ください。
具体値として、HEADERS フレーム 1 つにつき 1.57 バイトしか小さくならないという測定結果を提示されています。
2. 差分計算の複雑さ
Reference Set が外されたもう 1 つの大きな要因は、差分計算が必要となり実装が複雑になる点です。
サーバ側は、HTTP リクエストを受け取る度に「ヘッダの変更情報」と「既存の全てのヘッダの key, value」を比較し、差分を更新しないといけません。
当然、クライアント単位で独立して管理・保持する必要がありますし、クライアント側でもアクティブなヘッダの一覧をサーバと一致させ続けないといけません。
そして、仕様が動いた
Reference Set を仕様から外せば、
- 差分計算・保持に起因するバグの心配がなくなる
- ヘッダの順序が常に保持されるため、実装がシンプルになる
- 一方で、デメリットである圧縮率の劣化がごくわずかである
そういった議論により、HPACK-09 の仕様では Reference Set が削除 されることになりました。
まとめ
この一件は、HTTP2 の仕様がパブリックに議論・策定されていることを強く実感させるものでした。
これから HTTP2 の実装を始めたり、仕様を読み始めたりされる方にとって、この記事の情報は不要かもしれません。
それでも、HTTP2 のトリビアの 1 つとして、また、Reference Set の実装に多くの人が四苦八苦した記録として、この記事を投稿したいと思います。
余談
現在の仕様における正しい名称は HTTP2.0 ではなく "HTTP/2" もしくは "HTTP2" です。