11

我们必须使用delayed_job(或其他后台作业处理器)在后台运行作业,但我们不允许更改启动脚本/ boot服务器上的级别。这意味着如果提供程序重新启动服务器,守护程序不保证可用(因为守护程序将由仅在每次部署中运行一次的capistrano配方启动)。启动或确保延迟作业在应用程序/服务器重新启动时运行

目前,我能想到的确保delayed_job守护程序始终运行的最佳方式是向我们的Rails应用程序添加一个初始化程序,以检查守护程序是否正在运行。如果它没有运行,那么初始化程序启动守护进程,否则它就会保留。

因此,问题是我们如何检测Delayed_Job守护进程是从脚本内运行的? (我们应该能够很容易地启动守护进程,我不知道如何检测一个守护进程是否已经启动)。

任何人有任何想法?

问候, 伯尼

基于下面的答案,这是我想出了。只要把它在配置/初始化和你所有的设置:

#config/initializers/delayed_job.rb 

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid" 

def start_delayed_job 
    Thread.new do 
    `ruby script/delayed_job start` 
    end 
end 

def process_is_dead? 
    begin 
    pid = File.read(DELAYED_JOB_PID_PATH).strip 
    Process.kill(0, pid.to_i) 
    false 
    rescue 
    true 
    end 
end 

if !File.exist?(DELAYED_JOB_PID_PATH) && process_is_dead? 
    start_delayed_job 
end 
+0

在你的回答中,我们是否也应该提供'-e production'? – nathanvda 2010-09-14 12:19:46

+0

使用rails3这个解决方案不适合我。开始这个过程完全错误:它一直在开始额外的工作。我回到了卡皮斯特拉诺的任务:) – nathanvda 2010-09-14 12:54:21

回答

5

检查守护进程的PID文件(File.exist? ...)的存在。如果它在那里,那么假设它正在运行,否则启动它。

+0

太棒了!听起来很简单!你会不会在哪里可以找到该文件? – btelles 2010-04-05 20:59:53

+1

您会在您的应用的tmp/pids文件夹中找到该文件。您可能还想检查是否存在具有文件中ID的进程。 PID文件在崩溃后可能仍然存在。 – 2010-04-05 21:36:23

+0

优秀!谢谢!我会立即投票,然后等待一天或2天内是否有其他替代方案。 – btelles 2010-04-05 21:52:24

9

一些更多的清理想法:“开始”是不需要的。你应该拯救“没有这样的过程”,以便在出现其他问题时不发射新的过程。拯救“没有这样的文件或目录”以及简化条件。

DELAYED_JOB_PID_PATH = "#{Rails.root}/tmp/pids/delayed_job.pid" 

def start_delayed_job 
    Thread.new do 
    `ruby script/delayed_job start` 
    end 
end 

def daemon_is_running? 
    pid = File.read(DELAYED_JOB_PID_PATH).strip 
    Process.kill(0, pid.to_i) 
    true 
rescue Errno::ENOENT, Errno::ESRCH # file or process not found 
    false 
end 

start_delayed_job unless daemon_is_running? 

请记住,如果启动多个工作器,此代码将不起作用。并检查出产生监视器进程的script/delayed_job的“-m”参数以及守护进程。

0

非常感谢您提供的问题解决方案(以及启发它的答案:-)),即使对于多个工作人员(Rails 3.2.9,Ruby 1.9.3p327),它也适用于我。

它让我担心,我可能会忘记在对lib进行一些更改后重新启动delayed_job,例如,让我在实现之前进行几个小时的调试。

添加以下到我的script/rails文件,以允许在执行我们每次启动轨道,但每次都不工人开始时间的问题提供的代码:

puts "cleaning up delayed job pid..." 
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid', __FILE__) 
begin 
    File.delete(dj_pid_path) 
rescue Errno::ENOENT # file does not exist 
end 
puts "delayed_job ready." 

一个小缺点,我与此面对面的是,它也被称为rails generate例如。我没有花太多时间寻找解决方案,但欢迎提供建议:-)

请注意,如果您使用的是独角兽,则可能需要在调用before_fork之前将相同的代码添加到config/unicorn.rb

- 编辑: 周围多一点与上面的解决方案打后,我终于实现了以下内容:

我创建了一个文件script/start_delayed_job.rb与内容:

puts "cleaning up delayed job pid..." 
dj_pid_path = File.expand_path('../../tmp/pids/delayed_job.pid', __FILE__) 

def kill_delayed(path) 
    begin 
    pid = File.read(path).strip 
    Process.kill(0, pid.to_i) 
    false 
    rescue 
    true 
    end 
end 

kill_delayed(dj_pid_path) 

begin 
    File.delete(dj_pid_path) 
rescue Errno::ENOENT # file does not exist 
end 

# spawn delayed 
env = ARGV[1] 
puts "spawing delayed job in the same env: #{env}" 

# edited, next line has been replaced with the following on in order to ensure delayed job is running in the same environment as the one that spawned it 
#Process.spawn("ruby script/delayed_job start") 
system({ "RAILS_ENV" => env}, "ruby script/delayed_job start") 

puts "delayed_job ready." 

现在我可以在任何需要的位置需要这个文件,包括'script/rails'和'config/unicorn.rb':

# in top of script/rails 
START_DELAYED_PATH = File.expand_path('../start_delayed_job', __FILE__) 
require "#{START_DELAYED_PATH}" 

# in config/unicorn.rb, before before_fork, different expand_path 
START_DELAYED_PATH = File.expand_path('../../script/start_delayed_job', __FILE__) 
require "#{START_DELAYED_PATH}" 
0

不是很大,但工程

免责声明:我说不是很大,因为这会导致周期性的重启,这对于很多不理想。只要尝试启动可能会导致问题,因为如果创建了重复实例,则DJ的实现可能会锁定队列。

您可以安排cron定期运行以启动相关作业的任务。由于DJ在作业已经运行时将启动命令视为空操作,因此它可以正常工作。这种方法还处理DJ因某种原因而死亡的情况,而不是主机重新启动。

# crontab example 
0 * * * * /bin/bash -l -c 'cd /var/your-app/releases/20151207224034 && RAILS_ENV=production bundle exec script/delayed_job --queue=default -i=1 restart' 

如果您使用的是宝石像whenever这是非常简单的。

every 1.hour do 
    script "delayed_job --queue=default -i=1 restart" 
    script "delayed_job --queue=lowpri -i=2 restart" 
end 
相关问题