我如何告诉独角兽了解Heroku的信号?

时间:2012-03-07 16:47:01

标签: ruby heroku signals unicorn

也许你已经看过这个......

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

unicorn上运行heroku时,这是一个众所周知的问题...

我可以告诉heroku发送SIGQUIT吗?或者我可以告诉独角兽将SIGTERM视为优雅关闭吗?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:6)

这是一个黑客攻击,但我已经成功创建了一个独特的配置文件来捕获TERM信号,阻止独角兽接收它并执行快速关闭。然后,我的信号处理程序将QUIT信号发送回自身以触发独角兽正常关闭。

使用Ruby 1.9.2,Unicorn 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),但这只是多余的,不会影响任何内容。