WordPressをCentOS+Apache+mod_fastcgi+PHP-FPMを使って動かしてみた

このブログはさくら VPS で動かしているのですが、さくら VPS の一番弱いところはメモリの大きさが 512MB というところなんですよね。PHP みたいな LL は結構メモリは富豪的に使うので mod_php 使って httpd のメモリを膨れさせてると、同時接続数そんなに上げられないわけです。

アプリケーションサーバを WEB サーバと切り離すのであれば、定番としては WEB サーバとして Apache+mod_proxy や lighttpd や nginx を前段に置いて、 mod_php で起動した Apache にプロキシして上げるというのが一つのやり方です。 ただ、1 台のホストでやってるので Apache を 2 種類上げるとかなんか気持ち悪いし、 Apache 以外はあんまりよく分からない。

こんな時には、FastCGI を使って httpd から切り離すのが常套手段なんですが、 FastCGI を普通に使うと Apache の再起動と FastCGI プロセスの再起動が連動したりするのが 何となくすっきりしないですね。

Perl だと最近はこんな感じで plack で起動させたデーモンに mod_proxy で渡してしまうという手段があって すごい分かりやすくていい感じだなーと思っていて、PHP でこういうやり方が無いのかというのを 調べていたらありました。

PHP-FPMという仕組みがあって、あまりよく確認してないので 推測で書くと、PHP のインタプリタ的なものを適当なポートでデーモン起動させておくことができて、 WEB サーバからそのポートに向けて PHP のスクリプトをプロキシさせることで実現してるっぽいです。 (間違ってたらすいません><)

ただ、Google 先生に色々聞いてみても、nginx との組み合わせばっかりでてきて、Apache を WEB サーバとして使った場合どうやるのかなーと思ってたら、まさにバッチリなエントリを発見したので ほぼこのまんま導入してみたら、うまくいってしまいました。

というわけで、以下 CentOS5 でどうやったかの説明になります。

サードパーティの yum レポジトリ追加

CentOS5 の標準の yum レポジトリだと、php のバージョンが古かったりするので、 以下のレポジトリを追加しています。(rpmforge は php 入れる時の依存で libedit のために必要でした)

レポジトリの追加はこんな感じです。

cd /usr/local/src
wget http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
wget http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
rpm -ivh remi-release-5.rpm rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm

これだけだと、remi と rpmforge もデフォルトで使われてしまって困るパターンがあるので 通常時は使われないように conf を編集しておきます。

vim /etc/yum.repos.d/remi.repo
vim /etc/yum.repos.d/rpmforge.repo

# ファイルの中のenabled = 1を0に

# enabled = 1
enabled = 0

Apache のインストール

Apache はとりあえず CentOS 標準レポジトリのものを使ってます。 あとで mod_fastcgi の make をするために必要になるので httpd-devel も入れます。 devel の依存関係で他にも色々入ると思います。

yum install httpd httpd-devel

mod_fastcgi のインストール

mod_fastcgi は rpm が見つからなかったので make しています。32bit と 64bit で make のオプションが違うらしいですが さくら VPS は 64bit なのでこんな感じ。

cd /usr/local/src
wget http://www.fastcgi.com/dist/mod_fastcgi-2.4.6.tar.gz
tar xvzf mod_fastcgi-2.4.6.tar.gz
cd mod_fastcgi-2.4.6
cp Makefile.AP2 Makefile
make top_dir=/usr/lib64/httpd
make install top_dir=/usr/lib64/httpd

PHP 関係のインストール

僕の場合、MySQL を公式の rpm から入れてしまっているので、php-mysql だけ yum では入れられなかったので yumdownloader して rpm コマンドで入れてる以外は、remi からざくっと入れます。 もし MySQL も yum で入れてしまうなら、php-mysql も yum install でいいと思います。

yum --disablerepo=* --enablerepo=remi,rpmforge install php php-mbstring php-pdo php-fpm

# php-mysqlだけ別で
yum install yum-utils # yumdownloaderはこれに入ってます
cd /usr/local/src
yumdownloader --disablerepo=* --enablerepo=remi,rpmforge php-mysql
rpm -ivh --no-deps php-mysql-5.3.4-1.el5.remi.x86_64.rpm

各種 config の準備

これで必要なバイナリは揃ったので、あとは config の整備をしていきます。

/etc/httpd/conf/httpd.conf

各自のサイトに合わせて適当にやって頂ければと思います。 Apache2 系の conf は conf.d/*.conf に分割して書くのがメジャーらしいですが 僕は結構適当 httpd.conf に書いちゃってますw

標準の Apache は prefork でビルドされているので、WEB サーバの数の調整は <IfModule prefork.c>配下で調整しますが、アプリケーションの無い httpd プロセスはかなり小さいので あんまりシビアになる必要は無いと思います。

/etc/httpd/conf.d/php.conf

これは mod_php 用の config で、php-fpm で動かすには多分邪魔なのでコメントアウトするか どっかに移動するか消してしまいます。

/etc/httpd/conf.d/fastcgi.conf

さて、これが今回のキモになります。ファイルは無いので自分で新規作成。

LoadModule fastcgi_module modules/mod_fastcgi.so
<IfModule mod_fastcgi.c>
ScriptAlias /fcgi-bin/ "/etc/httpd/fcgi-bin/"
FastCGIExternalServer /etc/httpd/fcgi-bin/php-cgi -host 127.0.0.1:9000 -pass-header Authorization
AddHandler php-fastcgi .php
Action php-fastcgi /fcgi-bin/php-cgi
</IfModule>

中心は FastCGIExternalServer ですね。ここに指定したホストにプロキシしてくれます。 その他はあんまりよく理解してないですが、とりあえずコピペで動いちゃったので無視。

で、/etc/httpd/fcgi-binとか無いので、自分で作ります。

mkdir /etc/httpd/fcgi-bin
cp /usr/bin/php-cgi /etc/httpd/fcgi-bin/
chown -R apache: /etc/httpd/fcgi-bin
chmod -R 755 /etc/httpd/fcgi-bin

/etc/php-fpm.d/www.conf

こちらが PHP-FPM を制御する conf です。デフォルトだとプロセス数が負荷に応じて 増減する Apache の prefork と似たような設定になってますが、僕の目的としては PHP のプロセスの数を固定してメモリの使用量を一定にしておきたいのと 適当に再起動してもらってリークしていても増えないようにしたいのでこんな感じにしました。 これがやりたかったんだッ!人気ブログでもないので 3 つもあれば十分。

pm = static
pm.max_children = 3

pm.max_requests = 500

では起動!

WordPress は適当に配置してあるとします。(よく分からない人はとりあえず/var/www/html とかに展開しとけばよし) あとは PHP-FPM を起動して、Apache を起動すればもう動くよ!

service php-fpm start
service httpd start

まとめ

PHP を Apache とは別のプロセスで立ち上げて、メモリの使用量を一定にすることができました。 以前は mod_php で起動していて、prefork の設定を以下の様な感じにするという しょぼいやり方でメモリの使用量を抑えてました。

StartServers       5
MinSpareServers    5
MaxSpareServers   5
ServerLimit       5
MaxClients        5

まぁ悪くは無いんですが、httpd は php 以外にも画像とか css とかも返してるわけで、 あんまり数が少ないのはよろしくはありませんね。

今回 PHP-FPM を使ってプロセス数を固定にすることができたので安心して見ていることができます。 さくら VPS を使う場合にはくれぐれもメモリの使用量と swap 発生にはご注意を。