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 
相關問題