【问题标题】:Restart Unicorn with a USR2 - quitting old master用 USR2 重启 Unicorn - 退出老主人
【发布时间】:2011-08-13 05:51:45
【问题描述】:

因此,将 USR2 发送到 Unicorn 非常棒——它会使用您的代码的新副本启动一个新的 master,并自动获取任何更改。甜的。我的问题是:如何阻止老主人?显然接受的方式是在 before_fork 中:

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

这样做的问题是,一旦新主人(和新工人)产生,他们就会杀死旧主人。因此,对站点的任何请求都只是等待新的 worker 启动,通常会在整个 Rails 堆栈加载时等待几秒钟。

如果我删除我的 before_fork 一切都可以正常工作(从客户端的角度来看):我可以整天重新加载我的浏览器并且每个请求都很快得到满足,没有迹象表明新主人何时接管(除了看到我的代码更改现在出现)。但是,老主人现在挂了,直到我手动给它发送一个 QUIT。

据我所知,一旦工作人员完成加载并准备好为客户提供服务,就没有回调。这确实是我正在寻找的回调。我总是可以在 Rails 本身中创建一个初始化器,它会寻找一个旧的主人并杀死它,但这让我一想到它就心痛。

一定有办法!

【问题讨论】:

  • 我很确定 after_fork 工作人员在完成加载后会调用它们,您可能可以将代码放在那里..

标签: ruby-on-rails ruby unicorn


【解决方案1】:

如果preload_appfalse,那么向Unicorn master 发送HUP 信号似乎是一个更好的选择。

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

HUP - 重新加载配置文件和 优雅地重新启动所有工作人员。如果 “preload_app”指令为假( 默认),那么工人也会选择 任何应用程序代码更改时 重新启动。

【讨论】:

  • 实际上,如果preload_app为真,你应该使用USR2 + QUIT '如果“preload_app”为真,那么应用程序代码更改将无效;在这种情况下,必须使用 USR2 + QUIT 来加载更新的代码。'
  • 哎呀。我的意思是“如果 preload_app 为假”。
  • 如果之前是这样,那就不再是:即使 preload_app 为真,HUP 也会重新加载应用程序。
  • 当前文档 (unicorn.bogomips.org/SIGNALS.html) 似乎仍将 preload_app 列为要求。现在这不一样了吗?文档过时了吗?
【解决方案2】:

这是我的 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,这是一个很好的资源。

【讨论】:

  • USR2 没有为我创建 oldbin,可能是什么原因?
【解决方案3】:

我部分解决了这个问题:我看到的行为是由于没有使用preload_app true 引起的。如果你有这个设置,那么整个应用程序将由 master 加载,worker 的生成速度非常快。因此,如果第一个工作人员此时杀死了旧主人,那没关系,因为该工作人员可以立即开始服务请求!

如果您不能使用preload_app true,那么您最好的选择可能是将旧 pid-quit 行为移动到 Rails 初始化程序中,这样一旦 Rails 启动,启动您的应用程序的第一个工作人员就可以杀死旧主程序启动并准备好处理请求。

【讨论】:

    猜你喜欢
    • 2012-03-12
    • 2011-09-29
    • 2019-09-29
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多