6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Reference Set とは何だったのか

Posted at

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

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?