【问题标题】:How can I tell unicorn to understand Heroku's signals?如何让独角兽了解 Heroku 的信号?
【发布时间】:2012-03-25 05:31:33
【问题描述】:

也许你已经看到了……

2012-03-07T15:36:25+00:00 heroku[web.1]:使用 SIGTERM 停止进程 2012-03-07T15:36:36+00:00 heroku[web.1]:使用 SIGKILL 停止进程 2012-03-07T15:36:36+00:00 heroku[web.1]:错误 R12(退出超时)-> 进程未能在 SIGTERM 的 10 秒内退出 2012-03-07T15:36:38+00:00 heroku[web.1]:进程以状态 137 退出

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

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

【问题讨论】:

  • 我不知道。我正在考虑一个项目的独角兽,但这让我重新考虑。以下是 Thin 使用的信号:github.com/macournoyer/thin/blob/master/lib/thin/server.rb#L211 在这两种情况下,QUIT 表示正常关闭,但交换了 INT 和 TERM。
  • 顺便说一句,这里还有另一个因素——heroku 会将 TERM 发送到 Procfile 中定义的进程,但是该进程负责在它认为合适的时候传递信号。因此,如果您在 bundle exec 后面运行您的服务器,即使 heroku 发送了正确的信号,您也会看到上述行为,因为网络服务器根本没有收到信号。我已经讨论过这个问题,他们正在提出解决方案。
  • 今天发现了这个,还没探索:github.com/ddollar/foreman/wiki/Custom-Signals

标签: ruby heroku signals unicorn


【解决方案1】:

这是一个 hack,但我已经成功创建了一个 unicorn 配置文件,它捕获 TERM 信号,阻止 unicorn 接收它并执行其快速关闭。然后我的信号处理程序将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),但这只是多余的,不会影响任何事情。

【讨论】:

  • 这是公认的答案,因为帕特里克提出了 b4 heroku 多年以来的想法......但请参阅 Clay 的最新权威答案
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多