俺がやってみたかったh2oとphpの構成について
やっと暇ができたのでやってみました。
ところで、これをやりながらMicrosoftの発表見ていたんですが、マジですごい。Surface bookとかLumiaとか実際にモノを見てみないとなんともいえないけど、プレゼンだけでいえば完全にApple越えたプレゼンだった…。なんていうか、久々に発表で盛り上がった!
さておき
PHPのサーバー構築をシュッとやるのが個人的には結構面倒*1。理由はいくつかあるけれど
- 「他言語の感覚で」ウェブアプリを複数個、同一のサーバー(というより、バーチャルドメイン)で動かす時、キメラみたいなhtdocsを作るハメになるか魔法みたいなconfを書くハメになる。
- nginx+N個のApache+PHPをたてれば解決する場合もあるが 、apacheは複数飼うのは面倒。
- phpのバージョンを上げたり下げたり共存させたりが面倒(わかりきった事だが)、Apacheだとさらに面倒(apxsめんどい)
- やっぱりhttpdが欲しい、fastcgiだけではURLのbaseが変わるようなrewriteは設定面倒
- とにかくすっきり切り分けしたい!!
という感じ。
他の言語の世界では大体supervisordとかで起動したらhttpdがあがってきて上にnginxをかぶせる感じであり、PHPもそういう風にしたい!!!と思いつつ幾数年。
そこで気になっていたのがh2o+php-cgi、h2oなら軽量に、簡単にphpを管理できるのでは…?
PHPカンファレンスもおわったし(まだブログ書いて無い)やっと試した。以下はその手順である。
こういう構成はどうか?ということである
プロセスの親子関係的には
(systemd) -> supervisord -> ( H2O -> PHP(php-cgi) )
外から見たときはphpをh2oでwrapすることで、php自体がhttpdをもってるような見え方にしたい。
ファイルは、基本的に/opt
の下に全部がはいっている。
/opt /php PHPの一切合切 /h2o h2oの一切合切 /logs /sites/_/htdocs (まあどこでもいい)
手順
※ これはUbuntu 15での例です。
apt-get -y install libcurl4-openssl-dev libmcrypt-dev libreadline-dev libtidy-dev cmake git build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev libxml2-dev libgd-dev libxslt-dev libxml2-dev libgd-dev mkdir -p /opt/src mkdir -p /opt/logs chmod 777 /opt/logs mkdir -p /opt/site/_/htdocs echo "<?php phpinfo();" > /opt/site/_/htdocs/index.php # h2o のビルド cd /opt/src/ wget https://github.com/h2o/h2o/archive/v1.5.0.tar.gz tar xvzf v1.5.0.tar.gz cd h2o-1.5.0/ cmake -DWITH_BUNDLED_SSL=on -DCMAKE_INSTALL_PREFIX=/opt/h2o . make make install # phpのビルド cd /opt/src wget https://downloads.php.net/~ab/php-7.0.0RC4.tar.gz tar xvzf php-7.0.0RC4.tar.gz cd php-7.0.0RC4/ ./configure --prefix=/opt/php/ --with-gd --enable-sockets --with-jpeg-dir=/usr --with-png-dir=/usr --enable-exif --enable-zip --with-zlib --with-zlib-dir=/usr --with-kerberos --with-openssl --with-mcrypt=/usr --enable-soap --enable-xmlreader --with-xsl --enable-ftp --enable-cgi --with-curl=/usr --with-tidy --with-xmlrpc --enable-sysvsem --enable-sysvshm --enable-shmop --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-pdo-sqlite --enable-pcntl --with-readline --enable-mbstring --disable-debug --enable-fpm --enable-bcmath make make install
vi /opt/h2o/h2o.conf
pid-file: /opt/logs/h2o.pid access-log: /opt/logs/access.log error-log: /opt/logs/error.log user: nobody listen: 80 file.custom-handler: extension: .php fastcgi.spawn: "PHP_FCGI_CHILDREN=32 exec /opt/php/bin/php-cgi" hosts: "localhost:80": paths: /: file.dir: /opt/site/_/htdocs redirect: url: /index.php internal: YES status: 307
ここで、とりあえず起動できるかテスト。以下コマンドでh2oを起こして、ブラウザで開いてphpinfoがでてくればOK。
/opt/h2o/bin/h2o -c /opt/h2o/h2o.conf
問題なければsupervisordでデーモン化。
apt-get -y install supervisor
vi /etc/supervisor/conf.d/h2o.conf
[program:h2o] command=/opt/h2o/bin/h2o -c /opt/h2o/h2o.conf autorestart=true
service supervisor restart
完了。
個人的にはスーパーシンプルである。
プロセスはこんな感じになる
├─supervisord───h2o─┬─perl───php-cgi───10*[php-cgi] │ ├─perl │ └─2*[{h2o}]
まとめ
- アプリの数だけh2o.confとsupervisordの設定を書けば、複数のPHPアプリのサーバー*2を他の言語っぽく管理できそう
- phpが
/opt/php
に全部固まっているので見通し安いし、差し替えやすい*3。php-buildとかの相性良いと思う。 - つまり、タレ化(自動化w)しやすい
- H2Oをつかうと、php-fpmをつかわないでもphpプロセスが管理できるので、実質h2oだけ相手すればいい
- supervisordでh2oを起動しているので、initやupstartやsystemdの混乱に入らずに済む
実運用では、さらにこの上にnginxをかぶせる感じを想定している。
「h2oで配信すればHTTP/2でいいじゃん?持ち腐れでは?」というのはそうなのだが、実運用ではやはりもうちょっと各部に柔軟性がほしい*4
課題と展望
- ログをどうやって管理すっかなー…?
- 環境変数とかでPHPバイナリやコンフィグをシュッっと切り換えたりしてみたい。もっとphpを単なるプロセスとしてあつかいたい。
- まだ本番ではこの構成で運用してみてない、今度やってみる予定。
- 今気付いているのが、h2oのfastcgi.spawnはbacklogが少ない(?)ので、PHP_FCGI_CHILDREN(PHPプロセスの数)を少なくすると、100とか200とか同時接続を増やしたときに、ぼちぼちエラーがでる。雑にPHP_FCGI_CHILDRENをふやしたら解決したが、どこのところをいじったら待ち行列が伸ばせるのか?
- (とはいえ、私がやるようなメールフォーム案件とかで同時接続数100とか滅多に無いし、並べればいいので問題にはならない)
こちらからは以上です、ご意見お待ちしております。