Nginx de PHP

昨日書いたのがあまりに技術っぽくない(の割に結構見られてて恥ずかしい)ので、一応フォローのため「NginxでPHPを使う」ということに的を絞って書きます。

注意

  1. 基本的に「CentOS(バージョン5.7)環境での動かし方」を書いています
  2. ソースからビルドするので各種ライブラリや開発ツールが必要になります
    • Redhat系の場合は「yum groupinstall "Development Tools"」と叩いておけば大丈夫だと思います
    • それでも足りない場合はconfigure時に出るエラーを参照してググれば大抵は解決します(他力本願)
  3. かなり端折って書いているので「Linux操作をある程度知っていてApacheとかの設定をしたことがある人」が対象です

Nginxインストール

epelを入れてればyumでもインストールできますが、バージョンが若干古いことや、モジュールを自由に取ったり付けたりできるようにするため、ソースからビルドしてしまいます。
普通に使う分には以下のような手順でOKです。

  1. ここからソースをダウンロードして、適当な場所に置く
  2. 展開してソースをビルド&インストール

「ソースからビルド?なにそれこわい」とか思うかもしれませんが超簡単です。
足りないライブラリとか入ってないと闇から抜け出せなくなることも多々ありますが・・・。

ただし、昨日言った通り普通にビルドすると「Transfer-Encoding: chunked」に対応してないらしいので、対応させたい場合はモジュールを持ってきて一緒にビルドしてやる必要があります。
こいつがそのモジュールなので、落としてきて適当な場所に展開しておきましょう。

ソースからインストールすると、起動スクリプトがインストールされずプロセス管理が面倒なので、起動スクリプトも作っておきましょう。
ここから持ってきて、環境に合わせて弄ればとりあえずは動くんじゃないかと思います。

あ、あとNginxを実行するユーザーも作っておくといいんじゃないかと思います。
既にApacheが入っているならapacheユーザーで動かすのでもいいと思います。

$ cd /usr/local/src/
$ wget http://nginx.org/download/nginx-1.0.12.tar.gz
$ tar xvzf nginx-1.0.12.tar.gz
(出力省略)
$ cd nginx-1.0.12/

(普通にインストールする場合)
$ ./configure --with-http_stub_status_module
$ sudo make
$ sudo make install

(chunkedを有効にする場合)
$ ./configure --with-http_stub_status_module --add-module=/usr/local/src/agentzh-chunkin-nginx-module-ddc0dd5
$ sudo make -j2
$ sudo make install

PHPPHP-FPM)インストール

これもyumでインストールできる*1んですが、v5.1.6とかクソ古いバージョンが入ってたりするので、これもソースからビルドしてインストールしちゃっています。

ビルド方法は結構いろんな所で書いてあるのでビルドしたことのない方でもググればできるんじゃないかと思いますが、一応configureする際の要点だけ書きます。

  1. 「--enable-fpm」「--with-fpm-user=(nginxの実行ユーザー)」「--with-fpm-group=(nginxの実行グループ)」を入れる
  2. 「--with-apxs2」を外す(mod_phpとは同時にインストールできないらしいのでconfigure時にエラーになります)
  3. 既にいわゆる「Apache with mod_php」の環境で動かしていて、サービスを止めたくないあるいは併用したい場合は「--prefix」でインストールする先を変えればいいと思います

そもそも「PHP-FPM」ってなんなの?

NginxではApacheでの「mod_php」のようなモジュールが用意されていないため、外部のプロセスに処理を投げて、リクエストを処理して貰う必要があります。
そこで、PHPを処理するプロセスを管理してくれるのが「PHP-FPM(PHP-FastCGI Process Manager)」なのです。偉いですね。
ちなみに、FastCGIというのは「リクエストが来るたびにプロセスを作ったり捨てたりするなんてもったいない!予めプロセス用意しといて再利用すれば最強!」みたいな仕組みです。

PHP-FPM設定

PHP-FPMのデフォルト設定はPHPをインストールしたディレクトリの「etc」ディレクトリの中にあります。
もし「/usr/local/php/」にインストールした場合は「/usr/local/php/etc/」の中に「php-fpm.conf.default」があるはずなので、そいつを「php-fpm.conf」として同じ場所にコピーして色々と変更します。

設定で変えるべきところは

  1. 「user」「group」「listen.owner」「listen.group」をNginxを実行するユーザー/グループに合わせる
  2. 「pm」で始まる設定ほぼ全て
    • 「pm = static」にするとPHP-FPM起動時に一気に「pm.max_children」の数のプロセスを立ち上げる
      • よって同時に立ち上げるプロセスの数をメモリーと相談して増減させればいいんじゃないかと思います
    • 「pm = dynamic」にするとApacheのWorkerプロセスのように動的に増減。起動時には「pm.start_servers」の数だけプロセスを立ち上げる
      • staticの場合と同じく最大数をメモリーと相談しながら設定すれば多分なんとかなります
    • ずっと同じプロセス使ってるとメモリリークを起こしたりするので「pm.max_requests」である程度リクエスト処理したらプロセスを作りなおさせるようにしたほうが良さげです

プロセス1つあたりのメモリー消費量が思いの外少ない*2ため、「負荷が低い時に少しでもメモリーが欲しいよぉ><」ということでなければstaticにしてしまって搭載メモリー量に合わせてプロセスの数を調整するのが(プロセスを立ち上げたり切ったりする処理がない分)速度や負荷的にはよろしいんじゃないかと思います。

あと、これも起動スクリプトが自動的にはインストールされないっぽいですが、ちゃんと用意されているのでビルドしたあとに起動ファイルをコピーすればいいです。

$ cp /usr/local/src/php-5.3.10/sapi/fpm/php-fpm /etc/init.d/php-fpm
$ chmod 744 /etc/init.d/php-fpm

Nginx設定

上記のような手順でビルド&インストールすると「/usr/local/nginx/」以下にインストールしたもの一式が入るはず*3です。
設定ファイル一式は「/usr/local/nginx/conf/」以下にあります。

「nginx.conf」がApacheでの「httpd.conf」にあたるもので、Nginxの主な設定はここで全部やっちゃいます。
これもググれば適切な設定がいろいろ出てくると思いますので、要点だけ説明します。

  1. 「〜〜〜.php」のアクセスを「fastcgi_pass」を使ってPHP-FPMに投げる
  2. サーバー環境変数入れるために「include /usr/local/nginx/conf/fastcgi_params;」を入れる
  3. 「Transfer-Encoding: chunked」を有効にするためには設定を追加する必要あり
  4. 「worker_rlimit_nofile」「worker_connections」の数はファイルディスクリプタの数を増やす必要あり
  5. 用途にもよりますが基本的には「keepalive_timeout 0;」にしてKeepAliveを切っておいたほうがいい

以上を踏まえた設定例はこんな感じです。

worker_processes  2;
worker_rlimit_nofile 10240;

events {
    worker_connections  10240;
    use epoll;
}

http {
    keepalive_timeout 0;
    server_tokens off;

    server {
        listen 80;
        server_name xxxx.xxxxxx.com
    
        chunkin on;
        error_page 411 = @my_411_error;
        location @my_411_error {
            chunkin_resume;
        }
    
        location ~*\.php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /path_to_site/htdocs$fastcgi_script_name;
            include /usr/local/nginx/conf/fastcgi_params;
            fastcgi_send_timeout 15s;
            fastcgi_read_timeout 15s;
        }

        location ~ .*\.(jpg|JPG|gif|GIF|png|PNG|swf|SWF|css|CSS|js|JS|inc|INC|ico|ICO) {
            root /path_to_site/htdocs;
            break;
        }
    }
}

まとめ

NginxとPHPを使う場合のインストールと設定方法を簡単に説明しました。
要点だけ端折って説明したので、分からない事とか「ここおかしくない?」というところがあればTwitterとかはてブでツッコんでみたりして下さい。

*1:クラウドで用意されているサーバー用途のイメージファイルなら最初から入ってると思います

*2:Apache+mod_phpの半分くらい

*3:この辺は多分ディストリビューションによって変わりますし、「--prefix」オプションで変えられます