Posted at
HTTP2Day 8

Reference Set とは何だったのか

More than 3 years have passed since last update.


Referene Set とは何だったのか

この記事は HTTP2 Advent Calendar の 8 日目の投稿です。

この記事では、議論の過程で 仕様から外された技術 にフォーカスをあてて、「どういう技術だったのか」と「なぜ仕様から外されたのか」をお伝えします。

間違い等がございましたら、遠慮無くご指摘お願いします。


HPACK と失われし Reference Set

HTTP ヘッダの圧縮仕様は HPACK と呼ばれています。

現在の HPACK 仕様では 3 つの方法でヘッダをエンコードします。


  1. Literal


    • 単なる ASCII エンコード



  2. Huffman Encode


    • 出現頻度の高い文字をより小さいサイズで表現

    • 詳しくは 12/16 の Advent Calendar で解説する予定です



  3. 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" です。