unicornでダウンタイムなしに再起動する

ダウンタイム無しってすごい。
でも、そんな実行環境は今のところ必要ないので
monitの監視程度まで試したら、passengerに移行するやもしれません。

USR2時に旧プロセスを停止する

設定

ruby/1.9.1/gems/unicorn-4.1.1/examples/unicorn.conf.rb や unicorn.conf.rb
にサンプルがありますが
before_forkというcallbackが使えて、下記のように旧プロセスに対してシグナルを発行することが可能です。

    old_pid = "#{server.config[:pid]}.oldbin"
    if old_pid != server.pid
      begin
        sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
        Process.kill(sig, File.read(old_pid).to_i)
      rescue Errno::ENOENT, Errno::ESRCH
      end
    end
before
$ ps aux | grep unicorn
rochefort      3639 68.2 11.8 252860 60632 ?        Sl   13:09   0:11 unicorn master -D -E production -c config/unicorn.rb
rochefort      3655  0.0 11.1 252860 57040 ?        Sl   13:09   0:00 unicorn worker[0] -D -E production -c config/unicorn.rb
master再起動

kill -USR2 3639

$ ps aux | grep unicorn
rochefort      3639 25.7 11.8 252860 60632 ?        Sl   13:09   0:11 unicorn master (old) -D -E production -c config/unicorn.rb
rochefort      3655  0.6 11.5 254048 59080 ?        Sl   13:09   0:00 unicorn worker[0] -D -E production -c config/unicorn.rb
rochefort      3660 99.9  9.9 230752 50776 ?        Rl   13:10   0:10 /usr/local/bin/ruby /home/rochefort/.gem/ruby/1.9.1/bin/unicorn -D -E production -c config/unicorn.rb

元プロセス3639の名称がoldに変更。

after
$ ps aux | grep unicorn
rochefort      3660 67.4 11.6 251536 59536 ?        Sl   13:10   0:16 unicorn master -D -E production -c config/unicorn.rb
rochefort      3682  2.0 11.1 251796 56808 ?        Sl   13:10   0:00 unicorn worker[0] -D -E production -c config/unicorn.rb

新プロセス3660の名前がmasterに変更。


補足

シグナルおさらい

unicornでは、signalを投げてプロセスに命令を出します。
参考:File: unicorn_1
unicornコマンドで実行時に利用可能なsignalは下記。

sig description
HUP 設定リロード
INT/TERM プロセス即停止
QUIT graceful shutdown。現在のリクエストを処理してから停止
USR1 ログのリオープン
USR2 再起動※プロセスが残りますが、設定で旧プロセスを停止できます。(前述)
WINCH masterを止めずに、workerをgaraceful shutdown。
TTIN workerを1つ追加
TTOU workerを1つ削除