HTTP/2サーバーh2oでサーバプッシュを試してみた

HTTP/2 serverであるh2oで初めてのサーバプッシュを試してみた。

今回はh2o_mrubyも触ってみたかったということで、h2oをmrubyとともにビルドして少し触ってみた。

前回試してみたnginx_mrubyと同じくh2o_mrunyもサーバーをrubyで動的に制御することができる。

サーバプッシュとは

HTTP/1の場合、サーバーはクライアントからのリクエストに応じて、レスポンスを返すものでした。
しかし、HTTP/2の場合はクライアントからのリクエストがなくても、サーバーからレスポンスを返すことができる。

今回はresouce hintsにあるように、リクエストヘッダーにlink:<style.css>; rel=preload; as=stylesheet のようなLinkヘッダーを追加してレスポンスを返すようにした。

こうすることで、h2oサーバーは予めクライアントが次に何をリクエストするのか把握できる。
そして、クライアントがリクエストする前に、このファイルを返してくれる。

これにより、クライアントは次のリクエストからそのレスポンスまでの待ち時間(レイテンシ)を短縮できる。
そのため、これまでよりもブラウザは早く描画を行うことができるということになるっぽい。

構成

今回は、フロントにh2oを立たせて、リクエストをnginxにproxyする。
そして、nginx側でheaderにLinkヘッダーを追加してレスポンスを返す。

こうすることで、h2oはヘッダーを解釈して、サーバプッシュを行ってくれる。

手元の開発環境は以下の感じ
今回はサーバー側からプッシュする静的ファイルとして適当なcssをnginx側に追加しておいた。

h2o with mruby の構築

今回もubuntuで、以下のようにDcokerでコンテナをビルドした。

nginx の構築

nginxは前回と同じ感じで作成した。

nginx.confは以下のようにして

modify_header.rb でレスポンスヘッダーにLinkヘッダーを追加する。

ブラウザでアクセスできるようにPortFoward

boot2dockerをつかっているので、ブラウザでDcokerコンテナにアクセスできるようにPortFowardしておく。

Docker run

準備できたのでnginx、 h2oのコンテナを立ち上げていく。

nginxのipを泥臭く取ってきてから、h2oをビルドしてしまったが、
本当は Dockerとmrubyで迅速かつ容易にnginxとapacheの柔軟なリバースプロキシ構成を構築する にあるようにmrubyで動的変更できるように、環境変数を使って対応する予定でした。
しかし、h2o_mrubyを把握できてないのでうまくいかずに、今回は一旦保留とした。

とりあえず、これでブラウでアクセスしてみると分かりそう。

ブラウザ(Chrome)でアクセス

あらかじめ chrome://net-internals/#events を開いておき、ブラウザでh2oサーバーにアクセス。

すると、htmlへのリクエストはh2oでproxyされて、nginxのhtmlが帰ってくる。

このリクエストのhttpヘッダーを見ると

正しくLinkヘッダーが追加されている。

chrome://net-internals/#events で HTTP2_SESSION を確認すると

確かに、HTTP2_SESSION_RECV_PUSH_PROMISE とあり、サーバー側でpushしているのが確認できました。

今回はh2o_mrubyまで詳しく把握できなくて、ipを動的に変更できなかったが、おそらく切り替ることはできるだと思う。

また折を見て、h2o+mrubyを個人サービスのフロントに立たせてみることにチャレンジしてみようかな。

参考にしたページ
HTTP/2 入門
初めてのHTTP/2サーバプッシュ
HTTP2 時代のサーバサイドアーキテクチャ考察

Comments