2012-03-07 31 views
9

也許你已經看到了這個...如何告訴獨角獸瞭解Heroku的信號?

 
2012-03-07T15:36:25+00:00 heroku[web.1]: Stopping process with SIGTERM 
2012-03-07T15:36:36+00:00 heroku[web.1]: Stopping process with SIGKILL 
2012-03-07T15:36:36+00:00 heroku[web.1]: Error R12 (Exit timeout) -> Process failed to exit within 10 seconds of SIGTERM 
2012-03-07T15:36:38+00:00 heroku[web.1]: Process exited with status 137 

本上運行herokuunicorn時是一個衆所周知的問題...

燦我告訴heroku發送SIGQUIT?或者我可以告訴獨角獸將SIGTERM視爲優雅關機?

+0

我didin't知道,我正在考慮麒麟的一個項目,但是這讓我。重新考慮。以下是精簡使用的信號:https://github.com/macournoyer/thin/blob/master/lib/thin/server.rb#L211在這兩種情況下,QUIT表示正常關機,但INT和TERM交換。 – 2012-03-12 18:56:19

+1

順便說一句,這裏還有另一個因素 - heroku會將TERM發送到Procfile中定義的進程,但是該進程負責將信號按照它認爲合適的方式向下傳遞。因此,如果您在bundle exec後面運行服務器,即使heroku發送正確的信號,您也會看到上面的行爲,因爲Web服務器根本沒有得到信號。我已經談到支持這個,他們正在提出一個解決方案。 – 2012-03-12 18:58:20

+2

我今天發現這個,我還沒有探索它:https://github.com/ddollar/foreman/wiki/Custom-Signals – 2012-03-15 06:02:34

回答

6

這是一個黑客攻擊,但我已經成功創建了一個獨角獸配置文件​​,它捕獲TERM信號,防止獨角獸收到它並執行其快速關閉。然後我的信號處理器發送QUIT信號回自己觸發獨角獸正常關機。

測試使用Ruby 1.9.2,4.0.1獨角獸和4.2.1,Mac OS X的

listen 9292 
worker_processes 1 

# This is a hack. The code is run with 'before_fork' so it runs 
# *after* Unicorn installs its own TERM signal handler (which makes 
# this highly dependent on the Unicorn implementation details). 
# 
# We install our own signal handler for TERM and simply re-send a QUIT 
# signal to our self. 
before_fork do |_server, _worker| 
    Signal.trap 'TERM' do 
    puts 'intercepting TERM and sending myself QUIT instead' 
    Process.kill 'QUIT', Process.pid 
    end 
end 

一個問題是,(我相信)此信號處理器是由工作進程繼承。但是,工作進程安裝了自己的TERM處理程序,它應該覆蓋這個處理程序,所以我不會期望任何問題。 (見Unicorn::HttpServer#init_worker_process @ lib/unicorn/http_server.rb:551

編輯:。一個細節,這個塊安裝信號處理程序將每個工人的進程中運行一次(因爲before_fork),但是這僅僅是多餘的,不會造成任何影響

+2

這是被接受的答案,因爲帕特里克想出了它幾年b4 heroku做...但請參閱Clay對最新權威答案的回答 – 2013-03-05 16:41:45

9

的Heroku現在提供這說明在這裏: https://blog.heroku.com/archives/2013/2/27/unicorn_rails

他們提出unicorn.rb文件是:

# config/unicorn.rb 
worker_processes 3 
timeout 30 
preload_app true 

before_fork do |server, worker| 

    Signal.trap 'TERM' do 
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead' 
    Process.kill 'QUIT', Process.pid 
    end 

    defined?(ActiveRecord::Base) and 
    ActiveRecord::Base.connection.disconnect! 
end 

after_fork do |server, worker| 

    Signal.trap 'TERM' do 
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT' 
    end 

    defined?(ActiveRecord::Base) and 
    ActiveRecord::Base.establish_connection 
end