Unicornのダウンタイムなし再起動は考え無しに使うと危険

UnicornのプロセスにUSR2シグナルを送ると古いプロセスを残しつつ新しいプロセスが起ち上がるので、ダウンタイムが発生しない。
というのはUnicornの利点の一つとして数えられているが、実は罠なんじゃないだろうかと思い始めた。

USR2を送った直後の状態でプロセスのリストを見ると以下のようになる。(行が長いのでプロセス名の部分だけ抜粋)

akahige:# ps aux |grep unico
unicorn_rails master -E production -D --path /hoge-app -l0.0.0.0:8080                                          
unicorn_rails worker[0] -E production -D --path /hoge-app -l0.0.0.0:8080                                       
unicorn_rails master (old) -E production -D --path /hoge-app -l0.0.0.0:8080                     
unicorn_rails worker[0] -E production -D --path /hoge-app -l0.0.0.0:8080

見ての通りoldの方もまだ生きていてクライアントは両方にアクセスしに行く。
そのためダウンタイムがないのだけど、一方で変更前と変更後のサイトが交互に表示されるといったことが起きてしまったりする。
デザインの大幅変更などをした場合はかなりお粗末な状況となる。

しかも古い方が新しいプロセスが起ち上がってもなかなか死んでくれないんだよなあ・・・
デザインだけならいいけど、DBのスキーマの変更を行った場合は古い方が延々エラーを吐き続けるかもしれない。

考え無しに「ダウンタイムがないのっていいよね」で運用しているといつか痛い目に遭いそう。
つーか使いどころを選ぶフィーチャーだよねこれ。

また古い方のプロセスが残っている状態でCapistranoからdeploy:stopすると、stopの対象が新しいUnicornだけで、古い方は残り続ける。
しかもpidがもうCapistranoからは知ることができないのでstopできない。
こうなったらsshで入って手動killするほかない。

Railsのインフラはやっぱ難易度高いなあ。自由度の裏返しとはいえ。
個人的にはUnicornのパワーが必要になるようなサイトは作ってないし、Passengerに戻るべきか。

追記

USR2はMonitあたりから肥大化したUnicornのプロセスをやっつけたりするのに使うことを意図されているのかも。
デプロイに使うのは正しくなさそう。

2011/08/31追記

ふーむ。Twitterではデプロイに使ってるのか。

バックエンドが大量にある場合はもともとデプロイ時の新旧バージョンの混在には気を遣っていたりするのかな。
問題が出なければダウンタイムなしの恩恵は素直にありがたいだろうね。