HTTP2を試してみる

初めまして、インフラストラクチャ本部の後藤です。普段はChefを用いたサーバの自動構築環境の開発に従事しております。

今回は、近頃若者の間でも話題になっているHTTP2についてお話したいと思います。

HTTP2

2012年の末頃、HTTP1.1のセマンティクスを維持したままパフォーマンスを改善するという目的でHTTP2の仕様策定が開始されました。そんなHTTP2もワーキンググループ・ラストコールに向けて大詰めを迎えています。

現在最新版はdraft12となっており、すでに幾つかの実装が存在しています。HTTP2のwikiで確認できます。例えば、Google ChromeのCanaryビルドやFirefox Nightlyビルド では既にHTTP2が使用可能です。
またサービスとしては、twitter.com が対応しています。

HTTP2の特徴

HTTP2はGoogleの考案したSPDYと言うプロトコルをベースとしており、バイナリプロトコルになっています。SPDYはSSL上で、HTTPを効率よく転送する仕組みを提供します。HTTP2も同様の仕組みになっており、一つのTCPコネクションの上でHTTPリクエストやHTTPレスポンスを並列的に処理可能になっています。

ドメインごとに一つのTCPコネクションを使いまわすようになっており、HTTPリクエストのたびにTCPの3ウェイ・ハンドシェイクやSSLハンドシェイクを行う必要がなくなりました。昨今のブラウザはWebを閲覧するのに復数のTCPコネクションを使用していますが、HTTP2では使用するTCPの本数が少ないのでサーバやネットワーク機器の負担を減らす事にもなります。
さらに、それぞれのリクエスト・レスポンスが並列的に処理されるので、HTTP1.1で問題になっていたヘッドオブライン・ブロッキングは起こりません。

その他にも沢山の機能があり、非常にホットなプロトコルといえるでしょう。

  • HTTPヘッダの圧縮・差分転送(HPACK)
    • ヘッダをハフマン符号を用いて圧縮する
    • ヘッダを辞書のインデックスを用いて表現する
    • 前回のヘッダの差分のみ転送する
  • 優先付け(dependency-based stream prioritization)
    • クライアントがリソースをリクエストする際に優先度をサーバに伝えられる
    • リクエストの依存関係をサーバに伝えられる(例えば:CSSの次にJSが欲しい等)
  • サーバプッシュ
    • サーバは、クライアントからのリクエストが無くてもリソースを送信可能
    • クライアントは、送られてきたリソースはキャッシュ領域に保存する
  • パディング
    • SPDY3はHTTPヘッダを圧縮した上で暗号化を行っている。その特性を利用し、パケット長を観測することでHTTPヘッダを推測する攻撃が存在する。HTTP2では、任意長の無意味なデータを付加しメッセージの長さを変えることが可能
  • ネゴシエーション
    • HTTP1と同一ポートを用いるので、ネゴシエーションの仕組みが提供されている(全てがHTTP2の仕様というわけではありません)
    • SPDYと違いSSLの使用は必須ではない
  • フロー制御
    • 通信全体、並列化した通信単位でフロー制御が可能

実際に試す

実際にグリーで使用しているWebサーバでHTTP2を試してみました。図のようにWebサーバ内にHTTP2リバースプロキシを建てる構成です。HTTP2プロキシは、tatsuhiro-t氏によって開発されているnghttp2のnghttpxを利用します。

client-proxy-webserver

(仕様・実装ともに変更が加わりうるため、場合によっては正しく動作しない場合がございます)

nghttp2のインストール

nghttp2はdebianのunstableリポジトリにてパッケージが配布されています。sources.list にunstableリポジトリを追加することでapt-getで簡単にインストールできます。

/etc/apt/source.list に追記

nghttp2のインストール

リバースプロキシ起動

今回はデフォルトモードで起動します。デフォルトモードでは、HTTP2(TLS)を受け付けバックエンドにHTTP1.1でプロキシします。明示的に指定しない場合は、3000番ポートでリッスンします。

秘密鍵、証明書、バックエンドサーバの指定をして起動します。

クライアント準備

ChromiumのプロジェクトページのHTTP2のページを参考にして、chrome://flagsから HTTP2を有効にする。

enable http2

chrome://net-internals/#spdy にて実際にHTTP2でアクセスできていることが確認できます。
h2-12はHTTP2のdraft12の識別子です。

check using http2

FireFoxでは、about:config より、network.http.spdy.enabled.http2draftを有効にすることでHTTP2が使用できます。

実際にブラウザでアクセスする

実際にChromeでアクセスすると、GREEのトップページが正しく表示されてることが確認できます。

gree-top

キャッシュを無効化した状態で、デベロッパーツールのネットワークを見てみました。

HTTP1.1の場合
http1-network
HTTP2の場合
http2-network

HTTP1.1では後半の画像のリソースのダウンロードが遅れて開始されている事がわかります。これは、少ない並列数で順次ダウンロードを行っているためです。HTTP2では各リソースのダウンロードが均一に開始されていることがわかると思います。

これによりHTTPSで800msかかっていたページの表示がHTTP2では600msとなっています。よりネットワーク遅延の大きな環境では、この差はより大きくなると考えられます。

最後に

まだまだHTTP2の議論は続いています。
是非メーリングリストGithubのリポジトリを覗いてみて下さい。とてもホットで面白い話が多くあると思います。

最後に、Webの人もネットワークの人もプロトコル好きな人も、HTTP2に興味を持って頂ければ幸いです。
そしてHTTP2が少しでも盛り上がれば嬉しく思います。