2011-04-26 67 views
22

所以發送USR2到麒麟是真棒 - 它開始了一個新的主用你的代碼的新副本,並自動拿起任何更改。甜。我的問題是:我如何阻止老主人?顯然接受的方式是在before_fork:重啓獨角獸與USR2 - 戒菸老師傅

before_fork do |server,worker| 
    old_pid = '/var/www/current/tmp/pids/unicorn.pid.oldbin' 
    if File.exists?(old_pid) && server.pid != old_pid 
    begin 
     Process.kill("QUIT", File.read(old_pid).to_i) 
    rescue Errno::ENOENT, Errno::ESRCH 
     # someone else did our job for us 
    end 
    end 
end 

這樣做的問題是,一旦新的主(新工人)都產生了,他們殺舊主。因此,對站點的任何請求都只是坐在那裏等待新的工作人員啓動,通常在整個Rails堆棧加載時會持續幾秒鐘。

如果我刪除了我的before_fork,我希望從客戶端的角度來看,所有的工作都可以正常工作:我可以整天重新加載瀏覽器,並且每個請求都會被快速填充,沒有任何跡象表明新的主服務器何時接管比看到我的代碼更改現在顯示)。但是,老主人現在掛起,直到我手動發送一個QUIT。

據我知道有沒有回調,一旦工人加載完成,並準備爲客戶服務。這是我正在尋找的回調。我總是可以在Rails中創建一個初始化程序,尋找一個老主人並殺死它,但是這讓我的心痛得只是想着它而已。

必須有辦法!

+0

我敢肯定after_fork由工人叫一旦被加載完畢後,你很可能把代碼有.. – 2012-05-29 05:48:27

回答

16

我部分地解決了這個:我看到的行爲是不使用preload_app true造成的。如果你有這個集合,那麼整個應用程序都由主人加載,工作人員產生的速度非常快。因此,如果第一名工人在這一點上殺死了老主人,那麼這很好,因爲該工人可以立即開始提供請求!

如果你不能使用preload_app true那麼你最好的辦法就是將這個老式退出行爲移動到Rails初始化程序中,這樣一旦Rails啓動後,第一個啓動你的應用程序的worker就可以終止這個舊的master了並準備好爲請求提供服務。

+0

您正在運行多少個工作進程? – Ivan 2011-04-27 00:04:00

8

看起來,如果preload_appfalse,發送一個HUP信號給獨角獸主是一個更好的選擇。

http://unicorn.bogomips.org/SIGNALS.html

HUP - 重新加載配置文件和 平滑重啓所有工人。如果 「preload_app」指令爲false( 默認值),然後工人也會挑選 的任何應用程序代碼更改重新啓動時 。

+4

Acutally,如果preload_app爲true,則應該使用USR2 + QUIT '如果「preload_app」爲true,則應用程序代碼更改將不起作用;在這種情況下,USR2 + QUIT必須用於加載較新的代碼。' – astjohn 2011-05-28 01:45:31

+0

哎呦。我的意思是說「如果preload_app是錯誤的」。 – 2011-06-08 13:28:51

+1

如果以前這是真的,它不再是:即使preload_app爲真,HUP也會重新加載應用程序。 – Kevin 2013-06-13 17:47:08

3

以下是我在我的before_fork塊:

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 

重新啓動我的獨角獸我有了這樣的方法bash腳本:

if sig USR2 && sig 0 && oldsig QUIT 
then 
    n=$TIMEOUT 
    while test -s $old_pid && test $n -ge 0 
    do 
     printf '.' && sleep 1 && n=$(($n - 1)) 
    done 
    echo 

    if test $n -lt 0 && test -s $old_pid 
    then 
     echo >&2 "$old_pid still exists after $TIMEOUT seconds" 
     exit 1 
    fi 
    exit 0 
fi 
echo >&2 "Couldn't upgrade, starting '$CMD' instead" 
$CMD 
;; 

的bash腳本發送一個USR2信號,它分出新的獨角獸並創建舊的pid。然後它使用舊的pid發送舊的獨角獸QUIT信號。

這個過程確實很有效,並從Where Unicorns go to die: Watching unicorn workers with monit,這是一個很好的資源拍攝。

+0

USR2不爲我創建'oldbin',可能是什麼原因? – juanpastas 2016-06-28 14:22:12