FastCGI環境を構築する

長らくPHP屋をやっていたのでずっとmod_phpだったんだけど、いつかはFastCGIもやらんとなぁと思っていたところに、先日Tracでmod_fcgidを導入したのでおさらいしてみる。


以下はググって自分なりにまとめたものなので、認識が間違っているものもあるかもしれないので注意。

FastCGIのメリット

  • CGIプログラムのプロセスが常駐する
    • プログラムの起動オーバーヘッドがない
    • データやリソースをメモリ上で永続化できる(DBコネクションとか)
  • Webサーバに依存しない
    • 公開されたプロトコル
    • Webサーバと独立したプロセスで動く*1
      • 安定(プロセス的な意味で)
      • セキュア(プロセス的な(ry)
      • Webサーバが太らない(処理系のモジュールをロードしなくていいから)
      • バランシングや分散がやりやすい(WebサーバとCGIプログラムを別々のサーバにできる)
      • 言語処理系に問題があってスレッド型のMPMを使えない問題を解消できるかもしれない
  • suEXECできるっぽい(未調査、forkタイプだと無理?)
    • ユーザ毎にプロセスが必要らしい(当然か)

FastCGIのデメリット

  • プログラムをFastCGI用に書かなければいけない
    • どういう作法になるかは言語による(そのまま動作する言語もある)
    • ラッパーを利用すると通常のCGIプログラムをそのまま実行できる
      • FCGIWrapper(mod_fcgid)
  • プログラムを更新しても反映されない場合がある
    • プロセスが常駐したままなので再起動する必要がある
    • 言語によってまちまち(反映される、されない、インクルード類だけ反映されない、など)
  • リソースリークに、より一層注意を払わなければいけない
  • グローバル変数の明示的な初期化が必要
    • 以前の値が残っている*2
  • 実行時の環境などの融通が利かない
    • 環境変数
    • 実行時の特別な初期化処理(ライブラリのロード時のみに走る処理など)

ApacheFastCGIを利用するには

ApacheFastCGIを利用する場合は、次の三種類のモジュールがある。

現在の主流はmod_fcgidっぽい。
mod_proxy_fcgiはmod_proxyみたいな感じでバックエンドのFastCGIと通信するタイプのようだ(AJPとかのイメージ)。まだ若い?
前者2つがforkなのに対して、後者は完全に独立したFastCGIプロセスと通信(TCPまたはソケット)して処理するものになるようだ。これこそがFastCGIの真の姿なんだろうか。

mod_fcgidを入れてみる

Ubuntuの場合。

sudo apt-get install libapache2_mod_fcgid
sudo a2enmod fcgid

これだけ(どこかの醤油のCMみたいだ)。


設定ファイルは/etc/apache2/mods-available/fcgid.conf
最低でもhttp://fastcgi.coremail.cn/doc.htmを見て、MaxProcessCount、DefaultMinClassProcessCount、DefaultMaxClassProcessCountあたりは調整しておきたい。ついでにApache MPMのほうも調整しておいたほうがいい。
この辺をしっかり調整しないと処理をさばききれなくてリクエストが失敗するようになる。
デスクトップPCのバーチャルマシンみたいなリソースの乏しい環境で、テストがてらにabでも回そうものなら大変なことになる。

PHPFastCGIで動かす

PHPは他の言語とは少し違った動きをするようだ。
多くの言語がコンパイル済みプログラムをそのままプロセスに残すのに対し、PHPインタプリタだけを残してスクリプト自体は毎回コンパイルするらしい*3
毎回コンパイルするオーバーヘッドが生じるけど、反面スクリプトファイルを書き換えると即座に反映されることになる。他の言語の場合はプロセスを再起動する必要があるが、mod_fcgidの場合、つまるところApacheを再起動することになるので結構痛い。
PHPはmod_phpの使い勝手そのままという感じか*4。というかPHPにおけるFastCGIはmod_phpと大差ない気がしてきた。


設定には一工夫必要で、FCGIWrapperにCGI版のPHPインタプリタを指定する。

<Directory /var/www/php-fcgi>
    AddHandler fcgid-script .php
    FCGIWrapper /usr/bin/php-cgi .php
    Options +ExecCGI
</Directory>


スクリプトファイル側はShebang(#!/usr/bin/phpとかいうやつ)は必要ない。というか付けるとそのまま出力されるっぽい。
ただしパーミッションは実行権限を付けておく必要がある。

その他のこと

SpeedyCGIとか。

*1:ただし実現方法によってはサーバの子プロセスなので、親が死ぬと一緒に死ぬ。

*2:というかプログラムが再実行されてるわけじゃないので。

*3:FCGIWrapperを使わなければ他の言語と同じような動きになるような気もする。

*4:というか他の言語はmod_hogehogeでも再読込してくれないよね。