【SPDY / HPACK】HTTP/2ハッカソンに行ってきた

HTTP/2ハッカソン#1 (2014-02-23)に行ってきました。(当日資料)
HTTP/2関連情報はhttp2.infoでわかるので,改めて書くこともないですが,自分用のメモとして整理しておきます。

aa

HTTP/1.1おさらい

HTTP 1.1は1997年にRFCが発行され現在まで15年以上経過しています。
HTTP 1.1リクエストはtextベースで記述し行指定で処理していきます。
GETの場合,以下のように リクエストライン + HTTPヘッダ で構成されます。

GET /default.htm HTTP/1.1
Host: server.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8??Accept-Language: ja,en-us;q=0.7,en;q=0.3
Connection: keep-alive
/r/n

HTTP1.1はネットワーク効率が悪い, basic認証/digest認証というお世辞にもセキュアとは言うには物足りない認証方法という問題があります。
そもそもネットワーク速度は光速を超えられないという物理的な限界のため仕組み自体を変える必要があったのかもしれません。

HTTP/2

HTTP/2の目的のひとつはトラフィックを低減させることです。そのためヘッダ圧縮が行われバイナリベースでの通信を行うためHTTP1.1との互換性がありませんが, 後述するUpgradeを使う方法があります。
仕様策定はIETFという組織が行っています。
HTTP/2はdraft-10まで進んでおり2014年中にRFC発行との噂があります。

HTTP/2接続方法

1.TLS/ALPN
2.Direct(TLS/ALPNを省く)
3.HTTP1.1からのUpgrade
に分類されます。
URIスキームは http2://, web:// などが候補となっているようです。

ヘッダ圧縮

HPACKと呼ばれる圧縮方式でヘッダを圧縮します。元々の草案はGoogleのSPDYにあったEXI圧縮(text -> XML -> binary)です。
これは圧縮効率を高めるためにXMLタグをbit化しbinary表現にしてから,gzipなどで使われるdefrate圧縮する方法です。
HPACKはハフマン符号化はもちろん,ヘッダをあらかじめ定義して番号指定で短縮,前回のヘッダとの差分圧縮を含む圧縮方式です。

ちなみに,圧縮を使用しない場合のHTTP/2リクエストは以下のようになります。
HTTP 1.1のリクエストラインの3つのFieldを辞めKVSのように表現します。(method, scheme , pathが必須?)

:method: GET
:scheme: http
:path: /
:authority: www.example.com

またレスポンスは:statusでレスポンス番号だけで表現します。

Connection

HTTP/2接続の最も大きな概念がConnectionです。
connectionでTCP接続(あるいはUDP,TCPFastOpen)を行います。
(TLS ALPNが一番有力?)

Stream

connectionの中にはstreamが流れ双方向通信,複数存在することができます。
streamの中でリクエストとレスポンスを入れていきます。
streamはinterleave(混ぜて)で送信でき,stream_idはC->Sは奇数, S->Cは偶数で管理します。
0番は全体のフロー制御するために使われます。
また,stream_idは過去より大きな数字である必要があり, stream_idが32bit超えたら新しいコネクションを張り直します。

streamはFrame単位で管理されキュー構造で送信されます。以下,2つのFrameに分類されます。
HeaderFrame(従来のGET等のリクエストラインとヘッダー行)とDataFrame(従来のボディ行)に分かれます。

Frame

Frameという最小単位で通信します。
(SETTEINGフレームなど10種類くらい)

HTTP1.1からHTTP/2へのUpgrade

サーバがHTTP/2が話せるかわからない場合のためにHTTP1.1からUpgrade機能があります。

GET /default.htm HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: HTTP/2.0
HTTP2-Settings: 

レスポンス例です。

HTTP/1.1 101 Switching Protocols
Connection: Upgrade

ハッカソンの内容

各自HAPCK, HTTP2クライアント, HTTPサーバの実装を進めていくという内容でした。
私は当日数時間で相互通信の確認できるまでの実装ができませんでした。
主にNodejsCの実装中のCodeを見て勉強していました。

HPACKなどHTTP/2に関する討論

当日あった議論の内容を覚えている範囲で書いておきます。

  • HTTPは冪等性があり, 無限の同じリクエストに無限の同じ結果が得られる。これを利用した圧縮率観測攻撃ではデータ長がわかれば良くて暗号強度が関係なしの攻撃手法である。また総当たりの側面がありこれがHTTP/2では厄介となる。この圧縮率観測攻撃をカモフラージュするため0で埋めて送信するpaddingが事実上の標準となった場合,圧縮自体に意義があるのか。効率あげたら攻撃されるリスクが高まる。なら計算コスト分,deflateで良いのでは。
  • TLSだとカーネルランド(OS)とユーザランド(アプリ)のコンテキストスイッチが増えてくるので遅くなる可能性。ネットワークはカーネルから入るので, 今までカーネルで閉じ込めていたのがユーザランドで処理するとコンテキストスイッチが増えCPUコストが高まる弊害。
  • Upgrade機能の実装が増えていかないのでは。ハイパージャイアントはC/S握っていてちゃんと実装するしてくれるのか見えない。一部だけの利益にならないか。
  • アプリ開発者視点では, デバッギング難易度が上昇し実際はフルSSLの世界はきついのでは。しかし,いまのところのコンセンサスはヘッダ圧縮によって得られる利点には価値が大きい。(GoogleとかAkamaiにとってはそうなのでしょう)
  • draftは解決すべき問題が明確化されていないのではないか。(都度まとめられてはいる模様)

課題はあるにせよ未来を感じる HTTP/2 は胸が高鳴りますね。


[1] ALPN
[2] HPACK解説(ja)
[3] HPACK解説(ja)-2
[4] HPACK解説(en)
[5] Mark Nottingham Interview
[6] ヘッダ圧縮
[7] シアトルレポート
[8] 関連WG