我在nginx + unicorn后面运行了一系列Rails / Sinatra应用程序,零停机时间部署。我喜欢这种设置,但Unicorn需要一段时间才能完成重启,因此我希望在完成后发送一些通知。
我在Unicorn docs中找到的唯一回调与工人分叉有关,但我不认为这些可以为此工作。
这就是我从赏金中寻找的东西:旧的独角兽大师启动新的主人,然后启动其工人,然后旧的主人停止其工人并让新的主人接管。我希望在切换完成后执行一些ruby代码。
理想情况下,我不想实施任何复杂的流程监控来实现这一目标。如果这是唯一的方式,那就这样吧。但是在我走这条路之前,我正在寻找更简单的选择。
答案 0 :(得分:2)
我之前已经建立了这个,但它并不完全简单。
第一步是添加一个API,返回部署的当前代码版本的git SHA。例如,您部署AAAA。现在您部署BBBB并将返回。例如,假设您添加了返回SHA的api “/ checks / version”。
这是一个用于实现此API的示例Rails控制器。它假设存在capistrano REVISION文件,并在app加载时将当前版本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结构,其中app为/data/server/current
,端口为8080
上的本地独角兽。
答案 1 :(得分:0)
如果您拥有对该框的完全访问权限,则可以编写Unicorn脚本脚本以启动另一个脚本,该脚本循环检查将链接到正在运行的进程的/proc/<unicorn-pid>/exe
。
请参阅:Detect launching of programs on Linux platform
<强>更新强>
根据问题的变化,我看到两个选项 - 两者都不是很好,但它们仍然是选项......
你可以有一个每分钟运行一个Ruby脚本的cron作业监视PID目录mtime,然后确保存在PID文件(因为这会告诉你文件在目录中已经改变,而且过程是如果两个条件都为真,则执行其他代码。再次,这是丑陋的,并且是每分钟运行的一个cron,但它是最小的设置。
我知道你想避免复杂的监控,但这就是我尝试的方法......我会用monit来监控这些进程,当它们重新启动时,启动一个Ruby脚本睡眠(确保启动),然后检查进程的状态(可能再次使用monit本身)。如果这一切都正常返回,请执行其他Ruby代码。
选项#1不干净,但是当我编写monit选项时,我更喜欢它。