有点Rails的新手,所以请对付我。我现在正在做的是后台处理一些Ruby代码使用Resque。为了启动Rescque rake任务,我一直在使用(在heroku上),我有一个resque.rake文件,推荐的代码附加到heroku的神奇(或奇怪)线程架构中:
require "resque/tasks"
require 'resque_scheduler/tasks'
task "resque:setup" => :environment do
ENV['QUEUE'] = '*'
end
desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "resque:work"
因为我需要访问Rails代码,所以我引用:environment。如果我在heroku的后台设置至少1个工作dyno,我的Resque做得很好,被清除,一切都很开心。直到我尝试自动化东西...
所以我想改进代码并每分钟左右自动填充相关任务的队列。这样做(不使用cron,因为heroku不适合cron),我声明了一个名为task_scheduler.rb的初始化程序,它使用Rufus调度程序来运行任务:
scheduler = Rufus::Scheduler.start_new
scheduler.in '5s' do
autoprocessor_method
end
scheduler.every '1m' do
autoprocessor_method
end
事情看起来有点令人敬畏......然后,佣金流程就会无法解决地从队列中停止。队列越来越大。即使我有多个工作人员dynos在运行,他们最终都会感到疲倦并停止处理队列。我不确定我做错了什么,但我怀疑在我的rake任务中引用Rails环境导致task_scheduler.rb代码再次运行,导致重复调度。我想知道如果有人知道如何解决这个问题,我也很好奇,如果这是rake任务停止工作的原因。
谢谢
答案 0 :(得分:5)
您不应该在初始化程序中启动调度程序,您应该有一个守护程序进程运行调度程序并填满您的队列。它会是这样的(“脚本/调度程序”):
#!/usr/bin/env ruby
root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
Dir.chdir(root)
require 'rubygems'
gem 'daemons'
require 'daemons'
options = {
:dir_mode => :normal,
:dir => File.join(root, 'log'),
:log_output => true,
:backtrace => true,
:multiple => false
}
Daemons.run_proc("scheduler", options) do
Dir.chdir(root)
require(File.join(root, 'config', 'environment'))
scheduler = Rufus::Scheduler.start_new
scheduler.in '5s' do
autoprocessor_method
end
scheduler.every '1m' do
autoprocessor_method
end
end
您可以将此脚本称为应用程序中的常用守护程序:
script/scheduler start
这将确保您只有一个进程为resque worker发送工作,而不是为您正在运行的每个mongrel发送一个。
答案 1 :(得分:3)
首先,如果你没有在Heroku上运行,我不会推荐这种方法。我会看看Mauricio的答案,或考虑使用经典的cron作业或使用Whenever安排cron作业。
但是如果你在heroku上运行并试图这样做的话,我就是这样做的。
我保留了相同的原始Resque.rake代码,因为我粘贴在原始问题中。另外,我创建了另一个附加到作业的rake任务:work rake过程,就像第一种情况一样:
desc "Scheduler processor"
task :scheduler => :environment do
autoprocess_method
scheduler = Rufus::Scheduler.start_new
scheduler.every '1m' do
twitter_autoprocess
end
end
desc "Alias for resque:work (To run workers on Heroku)"
task "jobs:work" => "scheduler"
几个笔记:
我找到了进程挂起的原因。就是这行代码:
scheduler.in '5s' do
autoprocessor_method
end
我不知道为什么,但当我删除它时,它再也没有挂起。