ZabbixのフロントエンドをH2Oを使ってHTTP/2対応してみる

HTTPの新しい規格であるHTTP/2。
HTTP/2対応が簡単にできてしかも高速で動くと言われているWebサーバである[H2O](https://github.com/h2o/h2o)を使ってZabbixのフロントエンドのPHP WebGUIをHTTP/2化してみます。

Zabbixは設定を行ったり、監視結果を見たりする管理画面はPHPのWebアプリケーションとして稼働します。
通常、公開されているrpm等のパッケージからインストールした場合はApache HTTP Serverを使って構成するようになっています。

このApache HTTP ServerをH2Oで置き換えて、Zabbixの管理画面のGUIをHTTP/2化してみます。

前提となる環境は以下の通りです。

* OS: CentOS6.7
* Zabbix: 2.2.10
* PHP: 5.3.3
* H2O: 1.6.0

# H2Oのインストール

まずはH2Oをインストールします。
H2O自体はGithub上で公開されているのでここからソースコードを取得。

```shell-session
$ wget https://github.com/h2o/h2o/archive/v1.6.0.tar.gz
```

インストール作業に入る前にH2Oのbuildに必要なパッケージをインストールします。

```shell-session
$ sudo yum groupinstall "Development Tools"
$ sudo yum install libyaml-devel
$ sudo yum install cmake
```

H2Oのbuild&install
```shell-session
$ tar xvzf v1.6.0.tar.gz
$ cd h2o-1.6.0
$ cmake .
$ make h2o
$ sudo make install
```
これで/usr/local/bin以下にH2Oがインストールされます。

# SSL証明書の設定

HTTP/2自体はHTTPおよびHTTPSどちらでも対応していますが、ブラウザ(Chrome)から見るときにはHTTP宛だと自動的にブラウザ側でHTTP1.1で処理するため、サーバ側をHTTPSで対応できるようにしておきます。

今回はテストのため適当にSSLの自己署名証明書を発行しておきます。

```shell-session
# cd /etc/h2o
# openssl genrsa 2048 > cert.key
# openssl req -new -key cert.key  > cert.csr
# openssl x509 -days 3650 -req -signkey cert.key < cert.csr > cert.pem
```
※[参考]( http://lupinthe14th.github.io/h2o-http2.html#.VndL5dJ6SUk)

# h2o.conf設定

H2Oの起動時に引き渡す設定ファイル(/etc/h2o/h2o.conf)を新規作成し、以下のように設定を行います。

```shell-session:/etc/h2o/h2o.conf
user: apache 
listen: 80
listen:
  port: 443
  ssl:
    certificate-file: /etc/h2o/cert.pem
    key-file: /etc/h2o/cert.key
file.custom-handler:          
  extension: .php
  fastcgi.spawn: "PHP_FCGI_CHILDREN=10 exec /usr/bin/php-cgi"
hosts:
  default:
    paths:
      /zabbix:
        file.dir: /usr/share/zabbix
    access-log: /tmp/h2o_https_access.log
```

今回、Zabbixを公式のパッケージにてインストール済みの環境に対してH2Oを追加導入して設定を行っているので、php関連のファイルのアクセス権限の問題からH2Oの起動ユーザはapacheユーザを指定しています。
user:指定がない場合にはnobodyといったユーザにて実行されます。

cgiとして、php-cliに含まれているphp-cgiを利用して処理させています。
この設定を行うことで.php関連の処理がphp-cgi経由で処理を行います。
とてもシンプルで簡単です。

※[参考](http://blog.kazuhooku.com/2015/06/h2ophpmodrewrite.html)

# PHP関連設定をPHP側に設定

Zabbixの標準のApacheの設定ファイルだと以下のようにPHPの設定値をApache側の設定ファイルに指定されています。

```shell-session:/etc/httpd/conf.d/zabbix.conf
Alias /zabbix /usr/share/zabbix
＜Directory "/usr/share/zabbix"＞
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all

    php_value max_execution_time 300
    php_value memory_limit 128M
    php_value post_max_size 16M
    php_value upload_max_filesize 2M
    php_value max_input_time 300
    php_value date.timezone Asia/Tokyo
＜/Directory＞
・・・略
```

この設定をPHP側の設定ファイルに持っていきます。
一例として、/etc/php.iniに以下のように設定を行います。

```shell-session:/etc/php.ini
max_execution_time = 300
memory_limit = 128M
post_max_size = 16M
upload_max_filesize = 2M
max_input_time = 300
date.timezone = "Asia/Tokyo"
```

# H2O起動

起動は以下のコマンドの通り-cで設定ファイルを指定して実行するだけでOKです。

```shell-session
$ sudo /usr/local/bin/h2o -c /etc/h2o/h2o.conf &
```

起動すると、80ポート、443ポートにてサービスが立ち上がります。

# ブラウザからアクセス

あとは普通にブラウザからZabbixにアクセスすればOKです。
Chromeのエクステンションで「[HTTP/2 and SPDY indicator](https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin)」というのをインストールしておけば、ブラウザ上にHTTP2で通信していれば稲妻マークが表示されます。

では実際にhttps://でアクセスしてみましょう。

![h2o_稲妻マーク_change.png](https://qiita-image-store.s3.amazonaws.com/0/45851/bb3df5d4-2434-8592-dee5-4ebfbf798398.png)


無事HTTP2通信できています。

http://でアクセスすると表示されず、HTTP1.1にてアクセスしています。

![h2o_not稲妻マーク_change.png](https://qiita-image-store.s3.amazonaws.com/0/45851/9d012cf6-73a2-4060-489f-362d75a70b98.png)


# ちょっと試しに画像をたくさん表示するスクリーンにアクセスしてみる

HTTP2化できたので、その効果を確認するため、1ページで多くのリクエスト処理を行わなければならないスクリーンを作ってその際の通信を確認してみます。
スクリーン画面はこんな感じで1ページに10個のシンプルグラフを並べたもの。

![h2o_zabbix_screen.png](https://qiita-image-store.s3.amazonaws.com/0/45851/706e4c46-e2b8-4d0f-1e57-c5369ed491de.png)


## HTTP2通信

このページに対してhttpsでアクセスしHTTP2での挙動を見るとGoogleのDeveloper toolで確認したところ以下のような感じになっています。

![h2o_http2_network_change.png](https://qiita-image-store.s3.amazonaws.com/0/45851/b43401a6-19e7-72a3-3cd9-30a50e65405c.png)


この結果からわかるようにプロトコルとしてはh2を使っていて、各グラフの画像取得処理を全て並行でリクエスト送付して処理していることがわかります。

## HTTP1.1通信

次に、同じページに対してhttpでアクセスしHTTP1.1の挙動を見てみると、以下の図の通り、一度に送付しきれなかったリクエストがキューに貯められて段階を踏んでリクエスト処理されているのがわかります。

![h2o_http1_network_change.png](https://qiita-image-store.s3.amazonaws.com/0/45851/c324e407-0c08-d48f-ee75-31d6367e1a9d.png)


# まとめ

このようにHTTP2化することで通信処理自体は非常に効率よく行われます。ZabbixのWebGUIについても同様です。
しかし、Zabbixの場合、画面表示でボトルネックになる部分はどちらかと言うと、通信処理部分というよりZabbixが内部で監視結果を取ってきたりする部分であることが多いので本質的に画面の表示を速くするという点に対する効果は薄いかもしれないですね。
今回はHTTP2というかH2Oを少し試したかったということでこんなテーマでお届けしましたー
実際にやるならnginxとかがいいかもです。

Advent Calendarの記事も残りわずかになってきました。
次回の記事は[2box2boさん](http://qiita.com/2box2bo)です。よろしくお願いします！