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を利用します。
(仕様・実装ともに変更が加わりうるため、場合によっては正しく動作しない場合がございます)
nghttp2のインストール
nghttp2はdebianのunstableリポジトリにてパッケージが配布されています。sources.list にunstableリポジトリを追加することでapt-getで簡単にインストールできます。
/etc/apt/source.list に追記
1 |
deb http://ftp.us.debian.org/debian unstable main contrib non-free |
nghttp2のインストール
1 2 |
$ sudo apt-get update $ sudo apt-get install nghttp2 |
リバースプロキシ起動
今回はデフォルトモードで起動します。デフォルトモードでは、HTTP2(TLS)を受け付けバックエンドにHTTP1.1でプロキシします。明示的に指定しない場合は、3000番ポートでリッスンします。
秘密鍵、証明書、バックエンドサーバの指定をして起動します。
1 |
$ sudo /usr/sbin/nghttpx server.key server.crt --backend="localhost,80" |
クライアント準備
ChromiumのプロジェクトページのHTTP2のページを参考にして、chrome://flagsから HTTP2を有効にする。
chrome://net-internals/#spdy にて実際にHTTP2でアクセスできていることが確認できます。
h2-12はHTTP2のdraft12の識別子です。
FireFoxでは、about:config より、network.http.spdy.enabled.http2draftを有効にすることでHTTP2が使用できます。
実際にブラウザでアクセスする
実際にChromeでアクセスすると、GREEのトップページが正しく表示されてることが確認できます。
キャッシュを無効化した状態で、デベロッパーツールのネットワークを見てみました。
HTTP1.1では後半の画像のリソースのダウンロードが遅れて開始されている事がわかります。これは、少ない並列数で順次ダウンロードを行っているためです。HTTP2では各リソースのダウンロードが均一に開始されていることがわかると思います。
これによりHTTPSで800msかかっていたページの表示がHTTP2では600msとなっています。よりネットワーク遅延の大きな環境では、この差はより大きくなると考えられます。
最後に
まだまだHTTP2の議論は続いています。
是非メーリングリストやGithubのリポジトリを覗いてみて下さい。とてもホットで面白い話が多くあると思います。
最後に、Webの人もネットワークの人もプロトコル好きな人も、HTTP2に興味を持って頂ければ幸いです。
そしてHTTP2が少しでも盛り上がれば嬉しく思います。