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です