sekaie engineers' blog

セカイエ株式会社が主催するエンジニア勉強会について

HTTP/2 によるコンテンツ配信最適化検証 〜ストリームによる多重化編〜

こんにちは、まつはしです。 今日はセカイエ Advent Calendar 2015 7日目です。

HTTP/2 が RFC7540 で標準化され #1、Web 高速化プロトコルともてはやされていますが、ユーザのみなさんは本当により快適なサービスが享受できるようになるのでしょうか。セカイエが提供するリフォームサービス、リノコのコンテンツ配信を想定して実態を少しずつ検証していきましょう。

前置き

ネットワーク上で安全な通信路を構築するにあたり、第三者による盗聴検知が可能な量子暗号が実用化されていない現代、PKI に基づく通信相手の認証とその相手との強固な暗号化通信路の構築が主流となり、サービス提供者が信頼できる第三者機関の証明を受けてサービスを HTTPS 化していく流れは今後も拡大の一途をたどることでしょう。Google 検索エンジンHTTPS によるユーザメリットを高く評価し、サイトランキングに加味していることを発表しています #2。

HTTP/2 は RFC でこそ HTTP/HTTPS に対応しているものの、現時点では主要ブラウザの対応状況上、実質的に HTTPS が必須です。HTTP/2 にはコンテンツ配信をユーザ視点で最適化させるいくつかの仕組みが備わっています。この仕組みの中からユーザの快適性向上において大きな効果が期待できそうな、ストリームによる多重化、優先度制御の2点について検証してみます。

検証項目

  1. ストリームによる多重化 ★今日はここだけ
    • HTTP/1.1 までは 1 リクエストにつき 1 TCP セッションを占有していました。ブラウザは TCP セッションを確立するたびに TCP スロースタートからはじめらるため、有効帯域を使い切ることができないケースが多方面で生じていました。
    • HTTP/2 では単一の TCP セッション内でリクエストを多重化できます。ブラウザは TCP セッションの生存期間が長くなったため TCP のウィンドウサイズが適正値に調整され、有効帯域の利用を透過的に最大化する仕掛けが実現されました。アカマイのデモ を見ると効果は一目瞭然ですね。
    • 効果が分かりやすそうな、画像が多いページで比較検証してみます。
  2. 優先度制御 ★ここは後日書くかも?
    • HTTP/1.1 まではリクエストに対する優先度の制御ができず、ブラウザが最初に描画する領域 (以下、first-paint) のコンテンツを優先的に取得するといった制御ができませんでした。
    • HTTP/2 からはこの優先度制御の仕組みが備わりました。
    • first-paint の描画速度を比較検証してみたいとおもいます。

検証環境構築

HTTP/2 実装は主要なサーバ実装に取り込まれ始められ、nginx は Dropbox 社さん、Automattic 社さんのお力添えにより 1.9.5 より標準対応されています。今回は nginx を使い、投稿時点で最新版であった 1.9.7 で検証してみます。

Changes with nginx 1.9.5                                         22 Sep 2015

    *) Feature: the ngx_http_v2_module (replaces ngx_http_spdy_module).

*http://nginx.org/en/CHANGES

パッケージからインストールする場合

$ sudo rpm -Uvh http://nginx.org/packages/mainline/centos/6/x86_64/RPMS/nginx-1.9.7-1.el6.ngx.x86_64.rpm

ソースからインストールする場合

$ wget http://nginx.org/download/nginx-1.9.7.tar.gz
$ tar -xvf nginx-1.9.7.tar.gz
$ cd nginx-1.9.7
$ ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'
$ make
$ sudo make install
$ nginx -V
nginx version: nginx/1.9.7
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-threads --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

計測

セカイエで提供しているサービスの一画面でテストしてみます。

  • HTTP/1.1 ではリクエスト開始より 0.4 〜 1sec かけて TLS セッション 6本を確立。紫色の棒グラフが TLS セッション確立までに要した時間を表しています。その後、セッション毎にシリアルにリクエストが送受信されています。 f:id:sekaie:20151207234203p:plain

  • HTTP/2 ではリクエスト開始より TCP セッションを 1本のみ確立。その後は単一の TCP セッション内でストリームを通して同時並行でリクエストが飛ばされていることが確認できます。 f:id:sekaie:20151207234148p:plain

ですが、よくみるとレスポンス悪化してるんですよね。。サーバー側 t2.micro (CPU 1core オーバコミット有り、メモリ 1GB) のためリクエストをマルチでさばけないのが一因ではないかと思いましたが、後日お金をかけてじっくり検証してみたいとおもいます〜。

検証つづく

今日は時間が来てしまったので、、引き続き検証します・・。

ほな

資料

  1. IETF, HTTP/2 Approved
  2. Google Webmaster Central Blog, HTTPS as a ranking signal