我在Heroku的应用程序中添加了Resque-Scheduler
所以...我需要一个独立的,独特的工作人员充当调度员,许多人在做这些工作.
我就是这样做的:
我有一个独特的Heroku应用程序,除了拥有1个resque-scheduler worker,全天候运行,将Resque任务添加到"远程" 主应用程序的Redis DB之外什么都不做.
(我做那个映射工作:工作任务resque:调度程序或resque:工作)
这是在Heroku平台上做到这一点的最佳方式吗?还是我完全错了?
谢谢 !
编辑:在Heroku上安排的最小应用程序:http: //github.com/clmntlxndr/heroku-scheduler
更新:使用Heroku和Procfiles上的新CEDAR堆栈,可以为每个工作人员启动一个独特的任务.
web: bundle exec rails server -p $PORT
scheduler: bundle exec rake resque:scheduler
worker: bundle exec rake jobs:work
Run Code Online (Sandbox Code Playgroud)
我希望所有的enqueue调用都默认为某个队列,除非另有说明,所以它是DRY并且更容易维护.为了指定队列,文档说在类中定义变量@queue = X. 所以,我尝试了以下操作,它没有用,有什么想法吗?
class ResqueJob
class << self; attr_accessor :queue end
@queue = :app
end
class ChildJob < ResqueJob
def self.perform
end
end
Resque.enqueue(ChildJob)
Resque::NoQueueError: Jobs must be placed onto a queue.
from /Library/Ruby/Gems/1.8/gems/resque-1.10.0/lib/resque/job.rb:44:in `create'
from /Library/Ruby/Gems/1.8/gems/resque-1.10.0/lib/resque.rb:206:in `enqueue'
from (irb):5
Run Code Online (Sandbox Code Playgroud) 这里有一个开放式问题,所以我先概述一下这个问题.我们有一个Resque工作者应该从队列中弹出数据同步作业,原因是双重的,使用Cron(并且支持Rails环境引导时间一遍又一遍)很糟糕,以及替代队列,Github做的很好当他们宣布Resque时,他们是一个非常好的案例.此外,Redis时间序列功能已经成为我们基础设施的重要组成部分,我们还将TS数据混合到RRDTool等中......
这是问题,工作之间通常有三个小时(但工作人员可以随时安排工作......因此队列),PostgreSQL服务器消失了.足够容易治愈,我预计,设置reconnect: true相应的环境下,将确保这一预期一样.我在读一些 地方是reconnect: true不会为使用应用程序的工作fork().当然,Resque确实会启动它的工作人员...我不明白的部分是为什么ActiveRecord的重新连接在这些情况下无法工作?
我注意到的实现reconnect!了MySQL的适配器和PostgreSQL的适配器中的ActiveRecord是不同的......但无论哪种方式,我希望ActiveRecord的reconnect: true配置工作.
这个问题似乎很清楚,当子进程存在时,它会关闭父进程创建的文件句柄(从而挂断与数据库的连接) - 是否有可能以ActiveRecord不这样的方式关闭文件句柄认识到连接已经终止?
还有,值得一提的是,我能够在Github上找到一个ActiveRecord感知的fork()作为一个牧师 - 它没有经过测试,但我认为它有效(没有用当前的Rails试过......)
我的问题是,为什么不能自动重新连接AR工作如果你fork()?(而且,后来 - 我不能成为唯一一个遇到这个问题的人;我正在将它用于使用带有Resque的PGSQL!)
目前我们在JRuby中使用Resque,我们在开发时使用两种方式启动Worker.
QUEUE=* jruby -J-cp /path/to/library -S rake environment resque:workRun Code Online (Sandbox Code Playgroud)
def start
@worker = Resque::Worker.new(@queues)
@worker.verbose = @vervose
@worker.work(@interval)
end
def stop
@worker.try(:shutdown)
end
Run Code Online (Sandbox Code Playgroud)
虽然这两种解决方案都适合我们开发.我担心在部署到Tomcat时这将如何工作.
在Ruby中,通常会产生或妖魔化工作者,然后使用监视工具来监视pid.
在部署时以编程方式启动Workers是否有意义?我想知道它是否在java中启动一个新线程或者混乱了jruby进程,如果不是我应该使用,还有另一个像quartz这样的调度库来启动一个worker?或者在部署任务中启动的rake任务?
我可以创建一个Worker模型,然后跟踪数据库中的worker,但这对我没有意义.
任何帮助或知识将不胜感激.
谢谢.
参考文献:
https://github.com/defunkt/resque
http://rubydoc.info/github/defunkt/resque/master/Resque/
http://blog.thomasmango.com/post/636319317/resque-in-production
如果你在Heroku上的一个dyno上设置了Unicorn,那就说3个工人.是否有可能让2个子工作者处理Web请求,1个Unicorn子进行后台作业,例如resque队列或计划任务?
或者那是不合适的?
现在搞定了!
好的,所以使用下面的答案,我设法得到它来获取提示,但它首先需要一些修修补补.这对我有用.
Procfile
web: bundle exec unicorn_rails -p $PORT -c config/unicorn.rb
Run Code Online (Sandbox Code Playgroud)
unicorn.rb
worker_processes 2
preload_app true
timeout 30
@resque_pid = nil
before_fork do |server, worker|
@resque_pid ||= spawn("bundle exec rake environment resque:work QUEUE=*")
end
after_fork do |server, worker|
ActiveRecord::Base.establish_connection
end
Run Code Online (Sandbox Code Playgroud) 对于以下所有假设:
我们有3个型号:
当我们更新产品时(假设我们禁用它),我们需要在相关的sku和类别中发生一些事情.更新sku时也是如此.
实现这一目标的正确方法是after_save在每个模型上触发其他模型的更新事件.
例:
products.each(&:disable!)
# after_save triggers self.sku.products_updated
# and self.category.products_updated (self is product)
Run Code Online (Sandbox Code Playgroud)
现在,如果我们有5000种产品,我们就可以享用.相同的类别可能会更新数百次,并在执行此操作时占用数据库.
我们还有一个很好的排队系统,所以更实际的更新产品的方法products.each(&:queue_disable!)就是将5000个新任务简单地投入到工作队列中.但是仍然存在5000类别更新的问题.
有没有办法避免数据库上的所有更新?
我们如何连接队列中每个类别的所有category.products_updated?
该resque重试执行时,宝石的README讨论改变失败的后端实现.
MultipleWithRetrySuppression是一个多重故障后端,具有重试抑制功能.这是一个使用Redis故障后端的示例:
Run Code Online (Sandbox Code Playgroud)require 'resque-retry' require 'resque/failure/redis' # require your jobs & application code. Resque::Failure::MultipleWithRetrySuppression.classes = [Resque::Failure::Redis] Resque::Failure.backend = Resque::Failure::MultipleWithRetrySuppression如果作业失败,但可以并且将重试,则失败详细信息将不会记录在Redis失败队列中(通过resque-web可见).
如果作业失败,但不能或不会重试,则失败将记录在Redis失败的队列中,就像正常失败(没有重试)那样.
我不确定我的Rails应用程序中的代码应该去哪里.我应该将它放入任何随机初始化文件中,例如config/initializers/resque.rb?或者我的应用程序中还有其他地方应该去哪里?文件不清楚.
我正在使用Laravel 3制作一个网络刮板并拥有一个队列系统resque.
问题:我应该在哪里放置抓取逻辑代码?
在工人/工作班?
在由worker/job类静态调用的库类中?
在控制器功能中并且工作者/作业类触发控制器功能?
我目前在控制器功能中有它,所以我可以通过转到它的URL测试它.这也允许使用Cron重复作业,因为resque不允许重复作业.我仍然需要保留这种测试抓取功能的简单方法.
尝试:这是我在想的,你将如何为此目的组织代码?
工人阶级
class ScraperWorker
{
public function perform()
{
$url = $this->args['url']
Scraper::do_scrape($url);
}
}
Run Code Online (Sandbox Code Playgroud)
刮痧班
class Scraper
{
public static function do_scrape($url) {
//some scraping code
}
}
Run Code Online (Sandbox Code Playgroud)
控制器类
用于快速测试,以及用于Cron作业
class Scraper_Controller extends Base_Controller {
public function test_scrape($url) {
Scraper::do_scrape($url);
}
}
Run Code Online (Sandbox Code Playgroud) 我有Resque工作人员通常不应该花费大约1-5分钟的时间来运行,但是这些工人经常会"陷入困境"并且闲置,堵塞工人并无所事事.
因此,我想定期检查运行时间超过X时间的工人并清除它们.但我需要自动执行此操作,因此我不必Resque.workers.each {|w| w.unregister_worker}每隔几个小时亲自进入并手动清除它们().
这需要在Heroku上运行.
我有一个独立的resque工作队列,并希望使用包含的Web界面监视它,而不涉及任何rails应用程序.
我通过foreman管理我的进程,我的Procfile看起来像这样:
worker: bundle exec rake resque:work
web: bundle exec resque-web --foreground --app-dir /home/xxxx --server thin --port 5678 --no-launch
Run Code Online (Sandbox Code Playgroud)
为web生成的upstart脚本如下所示:
start on starting resque_cmd_runner-web
stop on stopping resque_cmd_runner-web
respawn
env PORT=5100
env PATH='/usr/local/rvm/gems/ruby-2.2.1/bin:/usr/local/rvm/gems/ruby-2.2.1@global/bin:/usr/local/rvm/rubies/ruby-2.2.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/rvm/bin:/usr/local/rvm/gems/ruby-2.2.1/bin:/usr/local/rvm/gems/ruby-2.2.1@global/bin:/usr/local/rvm/rubies/ruby-2.2.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/rvm/bin'
env GEM_PATH='/usr/local/rvm/gems/ruby-2.2.1:/usr/local/rvm/gems/ruby-2.2.1@global:/usr/local/rvm/gems/ruby-2.2.1:/usr/local/rvm/gems/ruby-2.2.1@global'
env QUEUE='*'
env RESQUE_WEB_HTTP_BASIC_AUTH_USER='xxxx'
env RESQUE_WEB_HTTP_BASIC_AUTH_PASSWORD='zzzz'
setuid xxxx
chdir /home/famulus/resque_cmd_runner
exec bundle exec resque-web --foreground --app-dir /home/famulus/resque_cmd_runner --server thin --port 5678 --no-launch
Run Code Online (Sandbox Code Playgroud)
但是,忽略HTTP BASIC AUTH的环境变量.我认为他们只是在resque-web gem中工作,而不是在resque中包含的界面中.
如何为包含的应用程序获取HTTP AUTH?
resque ×10
ruby ×5
heroku ×3
activerecord ×1
java ×1
jruby ×1
laravel ×1
mysql ×1
php ×1
postgresql ×1
queue ×1
rake ×1
redis ×1
resque-retry ×1
tomcat ×1
ubuntu ×1
unicorn ×1
web-scraping ×1