Ruby on rails 如何优雅地重新启动延迟的_作业使用者?
我想知道,在新的代码推送之后,优雅地重新启动延迟的\u作业消费者的最佳方式是什么?我正在使用capistrano推送代码,我知道有一些命令需要重新启动,但如果有作业当前正在运行,则该命令要么挂起(并且我的部署将永远持续),要么强制退出当前正在运行的作业,我将丢失数据 理想情况下,我希望我的部署如下:Ruby on rails 如何优雅地重新启动延迟的_作业使用者?,ruby-on-rails,capistrano,delayed-job,Ruby On Rails,Capistrano,Delayed Job,我想知道,在新的代码推送之后,优雅地重新启动延迟的\u作业消费者的最佳方式是什么?我正在使用capistrano推送代码,我知道有一些命令需要重新启动,但如果有作业当前正在运行,则该命令要么挂起(并且我的部署将永远持续),要么强制退出当前正在运行的作业,我将丢失数据 理想情况下,我希望我的部署如下: 现有的延迟作业使用者正在使用版本1代码运行 我运行capdeploy并将版本2代码推出到新服务器 在部署过程中,我们触摸一个文件,告诉延迟的_作业在处理完当前作业后重新启动。这可以通过多种不同的方式
capdeploy
并将版本2代码推出到新服务器def before(job)
# check to make sure that the version of code here is the right version of code
live_git_hash = LIVE_REVISION
local_git_hash = LOCAL_REVISION
if live_git_hash != local_git_hash
# get environment to reload in
environment = Rails.env # production, development, staging
# restart the delayed job system
%x("export RAILS_ENV=#{environment} && ./script/delayed_job restart")
end
end
它可以很好地检测到它,但它在shell调用时死亡。有什么想法吗
谢谢 想出了一个有效的解决方案 我有一个基类,我所有的延迟作业都从名为
BaseJob
的基类继承:
class BaseJob
attr_accessor :live_hash
def before(job)
# check to make sure that the version of code here is the right version of code
resp = HTTParty.get("#{Rails.application.config.root_url}/revision")
self.live_hash = resp.body.strip
end
def should_perform()
return self.live_hash == GIT_REVISION
end
def perform()
if self.should_perform == true
self.safe_perform()
end
end
def safe_perform()
# override this method in subclasses
end
def success(job)
if self.should_perform == false
# log stats here about a failure
# enqueue a new job of the same kind
new_job = DelayedJob.new
new_job.priority = job.priority
new_job.handler = job.handler
new_job.queue = job.queue
new_job.run_at = job.run_at
new_job.save
job.delete
# restart the delayed job system
%x("export RAILS_ENV=#{Rails.env} && ./script/delayed_job stop")
else
# log stats here about a success
end
end
end
所有基类都继承自BaseJob
并重写safe\u-perform
以实际执行其工作。关于上述代码的一些假设:
指向应用程序的根目录(即:www.myapp.com)Rails.application.config.root\u url
- 有一个公开的路由称为
(即:www.myapp.com/revision)/revision
- 您的应用程序知道一个名为“
的全局常量GIT\u REVISION
git rev parse HEAD
的输出放在一个文件中,并用代码推送它。这会在启动时加载,因此它在web版本以及延迟的作业消费者中都可用
当我们通过Capistrano部署代码时,我们不再停止、启动或重新启动延迟的作业使用者。我们在每分钟运行一次的使用者节点上安装一个cronjob,并确定是否正在运行延迟的作业进程。如果一个不是,那么一个新的将产生
因此,满足以下所有条件:
- 推送代码不再等待延迟的_作业重新启动/强制终止。推送新代码时,正在运行的现有作业将被单独保留
- 如果使用者正在运行旧代码,我们可以检测作业何时开始。工作被重新分配,消费者自杀
- 当延迟的_作业死亡时,通过带有新代码的cronjob生成一个新作业(根据启动延迟的_作业的性质,它有新代码)
- 如果您对杀死延迟的_作业消费者心存疑虑,请安装一个nagios检查,该检查与cron作业执行相同的操作,但在延迟的_作业进程未运行5分钟时会向您发出警告
延迟作业
上的引发信号_异常
配置选项,这里讨论:我知道很多年过去了,但有一个问题-如果我有5个延迟作业工人,该代码不会在其他作业运行时杀死它们吗?例如,work1-4运行长时间作业,work5检测到需要重新启动,它将杀死Worker 1-4,对吗?请注意,如果其他人尝试此方法,请不要尝试将延迟的\u作业停止
替换为重新启动
。。。这可能导致多次尝试同时重新启动运行,丢失PID,并导致大量不受控制的工作线程生成。解决方案指出,通过cron每分钟重新启动一次,这是一个很好的答案。多次停止是可以的(除了任务的内存开销之外),cron是唯一可以重新启动的东西。