Rails中组织工作进程的最佳方法是什么?

15

我经常有一些代码需要按计划或作为后台进程运行,带有一些参数。共同点是它们在调度过程之外运行,但需要访问Rails环境(可能还要访问传递的参数)。

如何有效组织这些代码,并解释原因?如果您喜欢使用特定的插件或gem,请解释您为什么认为它方便-不要只列出您使用的插件。

4个回答

8
我真的不喜欢像delayed_jobbackground_job这样的宝石,它们为运行异步作业而持久化到数据库。 对我来说,这似乎很肮脏。 短暂的东西不属于数据库。
我非常喜欢使用消息队列处理异步任务,即使您不需要大规模扩展性。 在我看来,消息队列是复杂系统的理想“通用语言”。 使用消息队列,在大多数情况下,您对参与构建的技术或语言没有限制。 低并发消息队列使用的好处在“企业级”环境中可能最为显着,因为集成总是非常麻烦的。 此外,当您的异步工作流涉及多个步骤时,消息队列是理想的选择。 RabbitMQ是我个人最喜欢的。
例如,考虑构建搜索引擎的情况。 人们可以提交要索引的URI。 显然,您不希望在请求中检索和索引页面。 所以你围绕一个消息队列构建:表单提交目标获取URI,将其抛入消息队列以进行索引。 下一个可用的蜘蛛进程从队列中弹出URI,检索页面,查找所有链接,如果它们未知,则将每个链接推回到队列中,并缓存内容。 最后,将一个新消息推送到第二个队列中,以供索引器进程处理缓存的内容。 索引器进程从队列中弹出该消息,并对缓存的内容进行索引。 当然过于简化了 - 搜索引擎是一项艰巨的工作,但您明白了。
至于实际的守护程序,显然,我偏爱自己的库(ChainGang),但它实际上只是一个围绕Kernel.fork()的包装器,为您提供了方便的位置来处理设置和拆卸代码。 它还没有完成。 实际上,守护程序部分远不及消息队列重要。
关于Rails环境,嗯,最好留给读者去练习,因为由于长时间运行的进程,内存使用量将是一个重要因素。 您不希望加载任何您不必要的东西。 顺便说一句,这是DataMapper在一个领域中远远超越ActiveRecord的地方。 环境初始化得到了很好的记录,并且涉及的依赖关系要少得多,使整个套件更加现实。
我不喜欢cron + rake的唯一一件事是,rake几乎肯定会打印到标准输出,而cron倾向于在cron作业产生输出时过于啰嗦。 我喜欢将所有的cron任务放在一个适当命名的目录中,然后制作一个包装它们的rake任务,以便手动运行它们非常简单。 真遗憾rake会这样做,因为我真的更喜欢有利用依赖项的选项。 无论如何,您只需直接将cron指向脚本,而不是通过cron运行它们。

我目前正在构建一个严重依赖异步处理的Web应用程序,我必须说,我非常非常高兴我决定不使用Rails。


你决定使用什么? - Yehuda Katz
Sinatra,DataMapper,Xapian,RabbitMQ - Bob Aman
实际上,我可能不会这么说。所讨论的应用程序是一个功能非常少的食谱搜索引擎,可以由iPhone应用程序调用。它有不到10个不同的页面,并且可能主要作为Web服务访问。绝大部分复杂性在于处理爬虫、解析和索引的异步进程。即便如此,它仍然主要是一堆库,之间的粘合代码尽可能少。不典型?肯定的。但我觉得这是我制作过的最优雅的Web应用程序之一。我认为这很相关。 - Bob Aman
@BobAman,现在delayed_job支持消息队列作为后端,你是否想修改你的观点? - VarunGupta
1
@VarunGupta 当然,那是在2009年写的。事情变了,这些信息现在大多已经过时了。尽管其中的情感和理由仍然有效。今天我可能会毫不犹豫地使用Resque而不是RabbitMQ。请随意编辑答案。 - Bob Aman
显示剩余2条评论

5

对我来说,不想维护大量额外的基础设施是一个关键优先级,因此我使用了在Rails之外运行的基于数据库的队列。

在我的情况下,我使用了background_jobdelayed_job。使用background_job时,工作进程通过cron保持运行,因此没有守护程序管理。而在使用delayed_job时,我正在使用Heroku并让他们担心这个问题。

使用delayed_job,您可以传递尽可能多的参数,以便您的后台工作者运行。

Delayed::Job.enqueue(MyJob.new(param[:one], param[:two], param[:three])

我尚未找到一个好的解决方案来按计划运行程序,除了使用cron通过script/runner(我更喜欢使用script/runner而不是Rake任务,因为我发现测试代码更容易)。
我从未需要定期安排后台进程以便访问特定的Rails请求,所以这并不是太大的问题。
我知道有其他更酷炫、功能更多的系统,但这对我来说已经足够好用,并且帮助我避免处理大量新服务的设置。

我想补充一点,虽然Yehuda已经接受了这个答案,但我认为对我最好的并不一定适用于其他人。作为一个糟糕的系统管理员,我的优先任务是减少系统管理员的工作量 :) 如果你有更多的技能或需要更高性能的解决方案,那么请尝试使用更奇特的排队系统之一。 - Luke Francl

2
我有一个系统,可以接收请求并需要使用Web服务调用多个外部系统。其中一些请求的响应时间超过了用户的预期等待时间,因此我使用企业级队列系统(ActiveMQ)来处理这些请求。
我正在使用ActiveMessaging插件来实现这一点。这使我能够将请求进行编组,并将其放置在队列中以进行异步处理,并且可以访问请求数据,但是如果您想等待响应,则需要编写轮询服务。
我看到了Ryan Bates关于Starling和Workling的railscast,它们看起来很有前途,但我没有使用过它们。

0
对于定期任务,我只使用Rake任务。它简单易用,易于测试、理解,并且与Rails环境很好地集成。然后,只需使用cron作业在所需的任何时间间隔内执行这些rake任务(我使用whenever管理这些作业,因为我略微不了解cron)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接