【问题标题】:Is it possible to send a notification when a Unicorn master finishes a restart?Unicorn master 完成重启时是否可以发送通知?
【发布时间】:2013-11-18 11:07:52
【问题描述】:

我在 nginx + unicorn 后面运行一系列 Rails/Sinatra 应用程序,部署时间为零。我喜欢这个设置,但是 Unicorn 需要一段时间才能完成重启,所以我想在它完成后发送一些通知。

我可以在 Unicorn 文档中找到的唯一回调与工人分叉有关,但我认为这些不会适用于此。

这就是我从赏金中寻找的内容:旧独角兽主人启动新主人,然后启动其工人,然后旧主人停止其工人并让新主人接管。我想在移交完成后执行一些 ruby​​ 代码。

理想情况下,我不想为此实施任何复杂的流程监控。如果这是唯一的方法,那就这样吧。但在走这条路之前,我正在寻找更简单的选择。

【问题讨论】:

  • 不能给这个文件打补丁吗? bogomips.org/unicorn.git/tree/lib/unicorn/launcher.rb
  • Github way(向下滚动到“缓慢部署”部分)不适合您吗?
  • @mudasobwa 这就是我正在做的事情。我认为你没有理解这个问题。
  • @AdamLassek 由于您已经使用该模式,我不明白是什么阻止您运行unicorn && my_ruby_script 而不是纯unicorn。可能我确实没看懂这个问题,抱歉。
  • @mudasobwa unicorn 命令不会直接重新启动,我们只是向进程发送 USR2 信号,告诉它启动一个新的主控。我不在乎新主人何时开始,我在乎它何时接管。

标签: ruby deployment nginx unicorn


【解决方案1】:

我之前已经构建过这个,但它并不完全简单。

第一步是添加一个 API,该 API 返回所部署代码的当前修订版本的 git SHA。例如,您部署 AAAA。现在您部署 BBBB 并将返回。例如,假设您添加了返回 SHA 的 api "/checks/version"

这是一个用于实现此 API 的示例 Rails 控制器。它假定 capistrano REVISION 文件存在,并在应用加载时将当前版本 SHA 读入内存:

class ChecksController
  VERSION = File.read(File.join(Rails.root, 'REVISION')) rescue 'UNKNOWN'

  def version
    render(:text => VERSION)
  end
end

然后,您可以通过 API 轮询本地独角兽的 SHA,并等待它更改为新版本。

这是一个使用 Capistrano 的示例,它将正在运行的应用版本 SHA 与新部署的应用版本 SHA 进行比较:

namespace :deploy do
  desc "Compare running app version to deployed app version"
  task :check_release_version, :roles => :app, :except => { :no_release => true } do
    timeout_at = Time.now + 60
    while( Time.now < timeout_at) do
      expected_version = capture("cat /data/server/current/REVISION")
      running_version = capture("curl -f http://localhost:8080/checks/version; exit 0")

      if expected_version.strip == running_version.strip
        puts "deploy:check_release_version: OK"
        break
      else
        puts "=[WARNING]==========================================================="
        puts "= Stale Code Version"
        puts "=[Expected]=========================================================="
        puts expected_version
        puts "=[Running]==========================================================="
        puts running_version
        puts "====================================================================="
        Kernel.sleep(10)
      end
    end
  end
end

您需要调整轮询的超时/重试次数以匹配您的平均应用启动时间。这个例子假设一个 capistrano 结构,应用在/data/server/current 和一个本地独角兽在端口8080

【讨论】:

  • 与我的生产环境存在一些差异,但我认为我可以做到这一点。
  • 这个任务应该是你可以在你的 unicorn restart cap 命令之后故意使用或链接的东西。很乐意帮助您解决环境的任何细节问题。
【解决方案2】:

如果您拥有对该框的完全访问权限,您可以编写 Unicorn 脚本以启动另一个脚本,该脚本循环检查 /proc/&lt;unicorn-pid&gt;/exe 将链接到正在运行的进程。

见:Detect launching of programs on Linux platform

更新

根据对问题的更改,我看到了两个选项 - 都不是很好,但它们仍然是选项......

  1. 您可以有一个 cron 作业,它每分钟运行一个 Ruby 脚本来监控 PID 目录 mtime,然后确保 PID 文件存在(因为这会告诉您目录中的文件已更改,并且进程正在running) 如果两个条件都为真,则执行附加代码。同样,这很丑陋,而且是一个每分钟运行一次的 cron,但它是最少的设置。

  2. 我知道你想避免复杂的监控,但这就是我尝试的方式...我会使用monit 来监控这些进程,当它们重新启动时,启动一个休眠的 Ruby 脚本(以确保启动),然后检查进程的状态(可能再次使用 monit 本身)。如果这一切都正确返回,请执行额外的 Ruby 代码。

选项 #1 不干净,但是当我编写 monit 选项时,我更喜欢它。

【讨论】:

  • 比这更复杂;新主人很早就开始了,但我想知道它什么时候完成加载工人并接管主人。
猜你喜欢
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多