Catalyst を daemontools で監視しつつ lighttpd の外部 FastCGI で走らせる方法とそのメリット

JPA セミナーの時に jshery 氏も勧めていましたし、近頃 Geek の話題で目立つようになってきた、Catalystmod_perl でなく、外部 FCGI として走らせる設定方法を紹介します。

Catalyst プロセスの起動管理は DJB 氏の daemontools による管理がお勧めです。プロセスが死んでも自動的に再起動してくれます。手動での再起動も楽です。screen からショートカットキー登録して Catalyst を再起動する方法も後ほど紹介します。

CatalystFastCGI 起動の設定

まずは daemontools の run スクリプトです。

run

#!/bin/sh
exec 2>&1
exec env - \
PATH='/bin:/usr/bin:/usr/local/bin:/var/www/www.example.com/script' \
DBIC_TRACE=1 \
CATALYST_DEBUG=1 \
DBIC_NO_WARN_BAD_PERL=1 \
setuidgid example \
myapp_fastcgi.pl -pidfile 'pid' -listen '/tmp/.s.www.example.com' -nproc 5 -keeperr \

ユーザー権限で Catalyst プロセスを走らせた方が色々と不便が無いので、 setuidgid を使っています。

次にログの run スクリプトです。multilog が自動的にログのローテートも面倒見てくれます。

log/run

#!/bin/sh
LOG=/var/log/www/www.example.com/
exec env - PATH='/usr/bin:/usr/local/bin' \
setuidgid example \
multilog s16777216 n4 \
-'* *Catalyst/View/ClearSilver.pm *' \
$LOG/all \
-'*' \
+'[debug] *' \
s4194304 n4 \
$LOG/debug \
-'*' \
+'[error] *' \
s4194304 n4 \
$LOG/fatal \
-'*' \
+'SELECT *' \
+'INSERT *' \
+'UPDATE *' \
+'DELETE *' \
s4194304 n4 \
$LOG/sql \

DBIC が吐くクエリログを別ディレクトリに分けています。

lighttpdFastCGI 設定

ログをチェックして Catalyst の起動ができたら、次に lighttpd の設定です。

lighttpd.conf

server.modules = (
    "mod_fastcgi",
)

$HTTP["host"] =~ "www\.example\.com" {
    # Static Files ===================== 
    server.document-root = "/var/www/www.example.com/static"
    # FastCGI ==========================
    $HTTP["url"] =~ "/[^/.]*(\?|$)" {
        fastcgi.server = (
            "" => ((
                "check-local" => "disable",
                "socket" => "/tmp/.s.www.example.com",
           ))
        )
    }
}

拡張子があるリクエストは lighttpd にサーブさせて、拡張子がないリクエストは FastCGI のソケットに渡しています。
特定の拡張子は Catalyst に渡したいときは、$HTTP["url"] の正規表現で調整します。

screen からショートカットキー一発で再起動

$HOME/.screenrc

# Send TERM signal to fcgi proccess
bind t exec bash -c 'cat /service/fcgi-www.example.com/pid | xargs kill -TERM'

ここで指定している /service/fcgi-www.example.com/pid は、Catalyst を起動するときに、myapp_fastcgi.pl -pidfile 'pid' で指定しているファイルです。

開発中にいちいち screen のウィンドウを root ユーザーのウィンドウに切り替えて、

svc -t /service/fcgi-www.example.com

と打つのも面倒臭いので、svc は root じゃないと実行できませんが、Catalyst プロセス自体は setuidgid で既にユーザー権限で走っているので、screen のショートカットキーに登録して楽に再起動できるようにしています。

外部 FastCGI のメリット

http://angelos.g.hatena.ne.jp/dann/20090603/1244029646

 少し調べてみて思ったのですが、多量のアクセスを捌くような必要があるケースでは、現状ではmod_perlでやったほうが楽なのかなぁという気がしました。これはApacheにプロセス管理をまかせられるからで、プロセスの管理をFCGI::ProcManagerなどでやるのはどうなんだろうなぁと思ったからでした。FastCGIの明白な利点というのがいまいち理解できなかったというのが正直なところで、FastCGIに乗り換える理由がいまはよくわからないなぁという印象です。
 FastCGIのほうがいいという人もいるわけで、何か見落としているような気もします... 引き続きもう少しFastCGIを使ってみようかなぁと思っているので、ここがFastCGIを使う事の最大のメリット!というのがあれば、是非教えてください。

FastCGI の最大のメリットは以下だと考えています。

  • フロントエンドの Web サーバー(Apache, lighttpd)を再起動する必要がない。
  • mod_perl のように、メモリ上で名前空間がぶつからない。

後者が重要で、例えば Catalyst をバージョン 5.7 で動かしたいアプリと、5.8 の Catamoose で動かしたいアプリと、同じ Web サーバーで複数のアプリを立ち上げようとしても、mod_perl では出来ません。外部 FastCGI の場合、ひとつのアプリが独立したひとつのプロセスとして走るので、各モジュールもそれぞれのプロセスのメモリの中にロードされますので、好きなモジュールの好きなバージョンを使えます。この辺は local::lib の使用とも絡んでくると思います。