Spinner,Spawner,Reaper
ふと思い付いてscript/process以下のスクリプトで遊んでみたんですが、まとまった日本語ドキュメントがなくちょっとはまりました。
で、見付けたSwichtowerのドキュメントの一部が比較的詳しかったので訳してみます。誤訳などがあれば教えてください。
Spinner
RailsにはFastCGIを制御するための三つのユーティリティ(spinnerとspawner、reaper)がある。
spinnerスクリプトはあなたのアプリケーションのscript/processディレクトリ内にある。(スクリプトがないのであれば、Railsを最新バージョンにする必要があるかもしれない。Rails 0.13.1がこのクリプトが含まれない最後のバージョンだ)
spinnerスクリプトは普通、spawnerによって起動されたFastCGIプロセスを監視するために実行され続ける。また、spinnerの起動時にFCGIプロセスを起動するコマンドを指定することもできる。このコマンドは大抵spawnerになるだろう。
/u/apps/flipper/current/scripts/process/spinner \ -c '/u/apps/flipper/current/scripts/process/spawner -p 7000 -i 5' \ -d
上の例では、spinnerは実行するコマンド(spawnerについては後述)を与えられ、デーモンとしてどうするように指定されている(-d スイッチ)。デフォルトではspinnerは与えられたコマンドを5秒毎に実行する。FastCGIリスナを起動させ続ける方法としては、どう見ても力技です。ありがとうございました。
こんなコマンドを何回も手入力するのはどう見ても非効率なので、これをscript/spinとして自分でコマンドにしちゃいます*1。
Spawner
spawnerスクリプトは複数のFastCGIリスナを産む(=spawn)ために使われる。たくさんのパラメータがある(spawn -h で確認できる)が、ここでは特に重要なもののみを取り上げる。
ということで、上記のspinnerのところで出てきた例では、spinnerがspawnerコマンドを実行するごとに(デフォルトでは5秒に一回)、7000-7004番ポートを使って5つのFastCGIリスナを起動させようとする。すでに起動しているリスナがportでlistenしている場合には、新たなリスナは起動しないので、実際には落ちてしまったリスナのぶんだけが起動しなおされる。
Reaper
reaperはspawnerの逆、すなわち起動している全てのFastCGIリスナを再起動させる(デフォルトではUSR2シグナルをリスナに送る)。
reaperはさらに(デフォルトでは)USR1シグナルをアクティブなspinnerプロセスにも送る。これによってspinnerは動きのギアを一段あげ、5秒毎に動くかわりに0.5秒毎にFastCGIプロセスを再起動させようとし始め、reaperが終了するときにspinnerのギアを通常どおりに下げる。こうすることで新しいリスナが再起動中にkillされた場合も、すぐに再起動するようになる。
これはつまり、いったんspinnerが動き出しさえすれせば、それに対してreaperを起動するだけでFastCGIプロセスを再起動できるってことだ。それ以外の処理は自動的に行われる。
restartタスクはデフォルトでは引数無しでreaperを起動するので、それ以外の再起動方法(例:USR2シグナルで再起動させるかわりにUSR1でkillしたい場合など)をとりたい場合は自分でrestartタスクを定義する必要がある。
以上
感想
- reaperはとても便利です。いままで/etc/init.d/apache2 restartとかをやっていたのが悪い冗談に思えてきます。
- lighttpd(apacheもですが)からFastCGIプロセスを起動している場合(よく紹介されている方法)はspawnerはたぶんいりません。reaperだけでWebサーバから起動されているFastCGIプロセス(dispatch.fcgi)が再起動するはずです。
- じゃあどういう時にspawnerを使うのかというと、WebサーバとFastCGIプロセスがTCP/IPでお話するときです。と思ってます。
- 具体的にはWebサーバとAPサーバを分離する場合になると思うんですが、このへんのやりかたはあとで書く。
- ちなみにspinnerで起動するのはspawnerに限りません。cronみたいなもの(ちょっと違いますが)です。ruby script/process/spinner -c 'date "+%Y%m%d %H:%M:%S"'とかをやってみると、動作イメージがつかめるかと思います。シンプルですが夢がひろがりんぐ。
この訳が誰かのお役に立ちますように。
*1:訳注:Switchtowerのチュートリアルの一部で、今後script/spinとして使われています。recipe/standard.rb内のデモなんかでも使われています。スクリプト化をせず、普通にscript/spinnerのまま使いつづけることも、もちろんOKです