リクエストを待たずに送信を開始する「サーバプッシュ」~奥一穂氏による「HTTPとサーバ技術の最新動向」(中編)。Developers Summit 2016
WebサーバはWebの誕生と同時に登場したソフトウェアですが、「HTTPとサーバの技術はまだ進化中」と説明するのは、新しいWebサーバの実装「H2O」の開発者であるディー・エヌ・エーの奥一穂氏。
HTTP/2の登場を背景に、いまHTTPとWebサーバの技術がどのように進化しているのか、Developers Summit 2016で行われた同氏のセッション「HTTP とサーバ技術の最新動向」の内容をダイジェストで紹介します。
記事は3部に分かれています。いまお読みの記事は中編です。
リクエストを待たずに送信を開始する「サーバプッシュ」
次はサーバプッシュの話です。
サーバプッシュとはなにか。HTTP/2の背景にはレイテンシをなんとかしたいということがありました。
しかしHTTP/2にしたところで、どうしても1RTT(一往復)かかります。なぜかというとHTTPはリクエストがないとレスポンスができないのですから。
でもリクエストを待たずにサーバからクライアントにデータを送りつけたら0RTTになるんじゃないか、というのがサーバプッシュです。
ではどういうときに使うのか。
RTTが50msで、アプリケーションサーバの処理時間が200msの場合を考えてみます。

Webブラウザからリクエストをすると、アプリケーションサーバの処理を200ms待ってHTMLが生成されて、そのあと全部のファイルを順番に取得すると、全体で450msかかります(図左)。
一方、アプリケーションサーバがHTMLを生成している200msのあいだにCSSやJavaScriptのファイルをプッシュしておけば、HTMLが届いた瞬間に、全体で250msでWebページが表示できます(図右)。
これはCDNでも使えます。CDNのエッジサーバは近いところにあるのですぐにリクエストを返しますが、アプリケーションサーバは西海岸にあったりして反応に時間がかかることがあります。

このとき、CDNにリクエストがきたらすぐにCSSやJavaScriptをクライアントに投げ始めて、その裏でリクエストを西海岸のサーバに投げれば、大幅に表示速度を改善できます。
ですが、サーバプッシュにはいろいろ問題があります。優先度制御との関係、プッシュをどう起動するのか、そしてブラウザキャッシュをどう意識するのかといった問題です。
サーバプッシュと優先度制御
サーバプッシュと優先制御ですが、これはRFC通りに実装しても役に立たないんですね。
なぜならサーバプッシュは、サーバプッシュを起動したリクエストより後に投げるとなっています。しかしHTMLを早く表示するためにはCSSを先に投げないといけないのです。一方で画像ならばHTMLより後に投げたい。
でもサーバプッシュはまだクライアントからリクエストが来ていないので、そういう優先度の指定もない。だからどうするかというと、サーバが自分で優先度を決めます。
H2Oでは、プッシュするコンテンツのタイプを見て優先度を決めています。JavaScriptやCSSはHTMLより優先で、画像ならHTMLより後にするという処理が入っています。

次はサーバプッシュをどうやって使うのか。こちらは標準化が進んでいます。
アプリケーションサーバがLinkヘッダがあって、これはこれから返すレスポンスに使えそうなリンクをヘッダに入れられるんですね。例えばstyle.cssをプリロードしなさい、という指示をHTTPヘッダに書けるようになっています。
これをH2OなどのHTTP/2実装が認識するので、アプリケーションサーバがこういうヘッダを返せばプッシュするようになります。
ただこれにも問題があります。
先ほど、アプリケーションサーバがリクエストを処理しているあいだにプッシュをしたい、と言いましたが、リクエストを処理中ということは、まだアプリケーションサーバがHTTPヘッダを送っていないわけですね。
けれどアプリケーションサーバがこのヘッダを送る前にプッシュをしたいわけです。
ということでどうやるか。これはWebサーバ側でやるしかないわけです。
H2Oでは、アプリケーションサーバへリクエストを転送する前にmrubyハンドラでいったんリクエストをトラップして、Linkヘッダだけ先に書いてしまいます。するとプッシュが始まります。

そのあとアプリケーションサーバにリクエストを転送します。こうすることでアプリケーションサーバの処理中にプッシュが可能になります。
キャッシュに入っている情報の送信を標準化議論中
Webブラウザのキャッシュとプッシュの関係です。
プッシュすればWebページの表示が早くなると言っても、Webブラウザのキャッシュに入っているものをわざわざプッシュしたくないわけです。
そのためにはWebサーバがWebブラウザのキャッシュに何が入っているのか知りたいのですが、プッシュする段階ではまだHTTPヘッダが届いていないので、判断のしようがないわけです。
じゃあどうしようか、ということでH2O 1.5以降に入っているのが「cache-aware server-push」です。

これはブラウザキャッシュ内のCSS、JavaScriptの一覧のフィンガープリントを圧縮して、すべてのブラウザからのリクエストにcookieとして添付します。H2Oはそれを基にプッシュを行うかを判定します。
ただ、キャッシュに何が入っているかはブラウザ以外には正確に分かりません。理想的にはWebブラウザがfingerprintを送信すべきなので、それは標準化しないとできないよね、ということで、現在IETFで標準化を議論中です。

≫次のページ「HTTPS化もHTTP/2にすれば負荷を下げられる」へ
Developers Summit 2016
- 5カ月でAngularJSとTypeScriptでSPAを開発。その技術の選択理由と開発過程は?(前編) Developers Summit 2016
- 強いチームを作るには時間がかかる~強いチームのつくり方(前編)。Developers Summit 2016
- レイテンシに負けないプロトコルとして登場したHTTP/2~奥一穂氏による「HTTPとサーバ技術の最新動向」(前編)。Developers Summit 2016
- Yahoo! Japanがアジャイル開発の採用と改善で現場から変えた“サービスの作り方”(前編)。Developers Summit 2016
- エンジニアを成長させるためのマネジメントと組織づくりとは~アドテクを中心とする組織の取り組みの例。Developers Summit 2016
あわせて読みたい
HTTPS化もHTTP/2にすれば負荷を下げられる~奥一穂氏による「HTTPとサーバ技術の最新動向」(後編)。Developers Summit 2016
≪前の記事
レイテンシに負けないプロトコルとして登場したHTTP/2~奥一穂氏による「HTTPとサーバ技術の最新動向」(前編)。Developers Summit 2016