当サイトを HTTP/2 対応
このサイトは2017年1月にさくらのVPS(vps.sakura.ad.jp
)を契約して HTTPS 化しましたが、当時は CentOS 7 の yum からインストールできる OpenSSL のバージョンが 1.0.1 だったため、 HTTP/2 対応ができませんでした(ソースからのインストールはなるべくやりたくないので)。
先日、ようやく OpenSSL 1.0.2 がインストールできるようになったので、 Apache と PHP の環境を再整備のうえ、 HTTP/2 に対応しました。
前提条件(というか対応前の環境)は以下のとおり。
- Apache 2.4、PHP 7.1 をインストール済
- PHP はモジュール版で動作
- TLS 接続対応済み(Let's Encrypt を使用)
- これらの環境構築については、「さくらのVPS」に移転した時に書いたさくらVPSでサイトをSSL/TLS対応(CentOS 7 + Apache 2.4 + PHP 7.1)を参照ください。
今回行う手順は以下のとおり。
- Apache をアップデート
- PHP をモジュール版から FastCGI に変更
- Apache の動作モードを prefork から event に変更
- Apache の設定ファイルに HTTP/2 の記述を追加
Apache のアップデート
Apache 2.4 は IUS のリポジトリからインストールするようにしていたので、次のようなオプションを指定してアップデート。
yum --disablerepo=base,extras,updates --enablerepo=ius update httpd
これで2017年11月1日現在、 CentOS 7 では Apache 2.4.28 + OpenSSL 1.0.2k にアップデートされます。
HTTP/2 導入準備(Apache 設定変更)
Apache の ChangeLog を見ると、2017年7月にリリースされた 2.4.27 でこんな変更がされたようです。
prefork モード(httpd.apache.org
)では HTTP/2 は使えなくなったようなので、これを worker か event に変更する必要があります。
ところが、そうするとモジュール版で動作させている PHP が使えなくなってしまいますので、先に PHP を CGI 動作に変更します。
FastCGI 導入
PHP を CGI で動作させるにあたり、 FastCGI の仕組みを導入します。以前は mod_fcgid と mod_fastcgi の2種類がありましたが、現在後者は公式サイトが閉鎖されてしまったようで、mod_fcgid(httpd.apache.org
)しか選択肢がありません。
yum -y install mod_fcgid
次に公式ドキュメントのコード例(httpd.apache.org
)に倣い、PHPのラッパースクリプトファイル( /usr/local/bin/php-wrapper )を作成します。
#!/bin/sh
PHP_FCGI_MAX_REQUESTS=10000
export PHP_FCGI_MAX_REQUESTS
exec /usr/bin/php-cgi
このファイルに対し、 apache ユーザーに実効権限を与えます。
chown apache /usr/local/bin/php-wrapper
chmod 744 /usr/local/bin/php-wrapper
続いて、 Apache の設定ファイル(httpd.conf や vhost.conf など)に以下の記述を追加します。
FcgidMaxRequestLen 104857600
FcgidMaxRequestsPerProcess 10000
<Directory "/var/www/w0s.jp">
AddHandler fcgid-script .php
Options ExecCGI FollowSymLinks
FcgidWrapper /usr/local/bin/php-wrapper .php
</Directory>
- 実際には他にも DocumentRoot などいろいろな設定を書いています。上記は今回追加した mod_fcgid 関連の記述のみを抜き出したものとなります。
FcgidMaxRequestLen は HTTP リクエストの最大長を指定するもので、デフォルト値は 131072(128KiB)(httpd.apache.org
)なのですが、ファイルのアップロード機能があるとこれでは足りないことが多く、その場合は 500 Internal Server Error が発生してしまいます[1]。このサイトでは動画ファイルをアップロードすることもあるので、大きめに 104857600(100MiB)を指定しました。
FcgidMaxRequestsPerProcess は FastCGI アプリケーションが処理するリクエスト数の上限値です。ラッパースクリプトの中で指定した PHP_FCGI_MAX_REQUESTS と同じか、それよりも小さい自然数を指定します。
またモジュール版の設定ファイルは不要になるので、以下のファイルの拡張子を .conf.bak 等に変更して読み込まれないようにします。
- /etc/httpd/conf.d/php.conf
- /etc/httpd/conf.modules.d/15-php.conf
Apache の動作を prefork → event に変更
MPMに関する設定ファイル /etc/httpd/conf.modules.d/00-mpm.conf を編集します。
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
↓
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_event_module modules/mod_mpm_event.so
↓
LoadModule mpm_event_module modules/mod_mpm_event.so
単純に読み込んでいるモジュールファイルを mod_mpm_prefork.so から mod_mpm_event.so に変更するだけですね。
いったん確認
ここまで行ったら Apache を再起動。
systemctl restart httpd.service
念のため、
apachectl -V | grep MPM
で Server MPM: event になっていることを確認(変更前は "prefork" )。
PHP に関しては phpinfo() して、 Server API が "CGI/FastCGI" になっていればOK(変更前は "Apache 2.0 Handler" )。
HTTP/2 設定
いよいよ HTTP/2 の設定を行います。といっても設定ファイルにProtocolsディレクティブ(httpd.apache.org
)の記述を書き足すだけです。
Protocols h2 http/1.1
- いくつかのブログ記事を拝見すると ProtocolsHonorOrder On の記述も併せて行っている方もいるようですが、これはデフォルト値が "on"(
httpd.apache.org
)なので、通常はわざわざ記述する必要はありません。
ブラウザで確認
Apache を再起動し、実際にブラウザでアクセスしてレスポンスヘッダーを見ると HTTP/2 通信が行われていることが確認できました。
また、 HTTP/2 に対応していないブラウザでは従来どおり HTTP/1.1 通信が行われます。
脚注
-
1.
Apache のエラーログには「mod_fcgid: HTTP request length 〓〓〓 (so far) exceeds MaxRequestLen (131072)」が書き込まれます。 ↩ 戻る