我经常有一些代码应该按计划运行,或者作为带有一些参数的后台进程运行。共同的元素是它们在调度过程之外运行,但需要访问 Rails 环境(可能还有传入的参数)。
什么是组织这个的好方法,为什么?如果您喜欢使用特定的插件或 gem,请解释您觉得它方便的原因——不要只列出您使用的插件。
我经常有一些代码应该按计划运行,或者作为带有一些参数的后台进程运行。共同的元素是它们在调度过程之外运行,但需要访问 Rails 环境(可能还有传入的参数)。
什么是组织这个的好方法,为什么?如果您喜欢使用特定的插件或 gem,请解释您觉得它方便的原因——不要只列出您使用的插件。
我真的不喜欢为了运行异步作业而持久保存到数据库中的delayed_job
宝石。background_job
我觉得它很脏。瞬态的东西不属于数据库。
我非常喜欢处理异步任务的消息队列,即使你不需要大规模的可伸缩性。在我看来,消息队列是复杂系统的理想“通用语”。在大多数情况下,使用消息队列,您对所构建的任何内容所涉及的技术或语言都没有任何限制。使用低并发消息队列的好处可能在“企业”环境中最为明显,因为集成总是一个巨大的痛苦。此外,当您的异步工作流涉及多个步骤时,消息队列是理想的选择。RabbitMQ 是我个人的最爱。
例如,考虑您正在构建搜索引擎的场景。人们可以提交要编入索引的 URI。显然,您不想在请求中检索和索引页面。因此,您围绕消息队列构建:表单提交目标获取 URI,将其放入要索引的消息队列中。下一个可用的蜘蛛进程将 URI 从队列中弹出,检索页面,找到所有链接,如果它们是未知的,则将它们中的每一个推回队列,并缓存内容。最后,一条新消息被推送到第二个队列中,以便索引器进程处理缓存的内容。索引器进程将该消息从队列中弹出,并对缓存的内容进行索引。当然过于简单了——搜索引擎需要做很多工作,但你明白了。
至于实际的守护进程,很明显,我偏爱我自己的库(ChainGang),但它实际上只是 Kernel.fork() 的一个包装器,它为您提供了一个方便的地方来处理设置和拆卸代码。它还没有完全完成。守护进程远没有消息队列重要,真的。
关于 Rails 环境,好吧,这可能最好留给读者作为练习,因为内存使用将成为长时间运行的进程的一个重要因素。你不想加载任何你不需要的东西。顺便说一句,这是 DataMapper 对 ActiveRecord 的有力打击的一个领域。环境初始化是有据可查的,并且发挥作用的依赖项要少得多,这使得整个套件和 caboodle 更加逼真。
我不喜欢 cron+rake 的一件事是 rake 实际上可以保证打印到标准输出,如果您的 cron 作业产生输出,则 cron 往往过于健谈。我喜欢将我所有的 cron 任务放在一个适当命名的目录中,然后制作一个包装它们的 rake 任务,这样手动运行它们就很简单了。rake 这样做很可惜,因为我真的更愿意选择利用依赖关系。在任何情况下,您只需将 cron 直接指向脚本,而不是通过 cron 运行它们。
我目前正在构建一个严重依赖异步进程的 Web 应用程序,我不得不说,我非常非常高兴我决定不使用 Rails。
对我来说,不想维护大量额外的基础设施是一个关键的优先事项,所以我使用了在 Rails 之外运行的数据库支持的队列。
就我而言,我使用了background_job
和delayed_job。有了background_job
,worker 一直通过 cron 运行,因此没有守护进程管理。有了delayed_job
,我正在使用 Heroku 并让他们担心。
使用delayed_job,您可以传入后台工作人员需要运行的尽可能多的参数。
Delayed::Job.enqueue(MyJob.new(param[:one], param[:two], param[:three])
除了script/runner
通过 cron 使用之外,我还没有找到按计划运行东西的好解决方案(我更喜欢使用script/runner
Rake 任务,因为我发现测试代码更容易)。
我从来不需要定期安排需要访问特定 Rails 请求的后台进程,所以这不是什么大问题。
我知道还有其他更酷的系统具有更多功能,但这对我来说效果很好,并且帮助我避免处理设置许多新服务来管理。
我有一个接收请求的系统,然后需要使用 Web 服务调用多个外部系统。其中一些请求花费的时间比用户预期的要长,我使用企业排队系统(activemq)来处理这些请求。
我正在使用ActiveMessaging插件来执行此操作。这使我可以编组请求并将其放在队列中以进行异步处理并访问请求数据,但是如果要等待响应,则需要编写轮询服务。
我在Starling 和 Workling上看过 Ryan Bates railscast ,它们看起来很有希望,但我没有使用它们。
对于定期安排的任务,我只使用 rake 任务。它简单、易于测试、易于理解并与 Rails 环境很好地集成。然后只需在您需要的任何时间间隔使用 cron 作业执行这些 rake 任务(我使用任何时候来管理这些作业,因为我对 cron 不识字)。