Rails App在后台运行长任务的最佳实践?

时间:2009-02-03 19:59:31

标签: ruby-on-rails ruby

我有一个Rails应用程序,不幸的是,在向控制器发出请求后,必须进行一些需要一段时间的运算。 Rails中为长期运行的任务或请求提供反馈或进度的最佳做法是什么?这些控制器方法通常持续60秒以上。

我不关心客户端......我计划每隔一秒左右发出一次Ajax请求并显示进度指示器。我只是不确定Rails最佳实践,我是否创建了一个额外的控制器?我能做些什么聪明的事吗?我希望只使用Rails专注于服务器端的答案。

提前感谢您的帮助。

编辑:

如果重要,http请求适用于PDF。然后我将Rails与Ruport一起生成这些PDF。问题是,这些PDF非常大并且包含大量数据。使用后台任务仍然有意义吗?假设平均PDF需要大约一分钟到两分钟,这会使我的Rails应用程序在此期间对任何其他服务器请求没有响应吗?

编辑2:

好的,经过进一步调查后,似乎我的Rails应用程序在请求大型PDF后确实没有响应任何其他HTTP请求。 所以,我想现在的问题是:使用什么是最好的线程/后台机制?它必须稳定并保持。我很惊讶Rails没有内置的东西。

编辑3:

我已阅读此页:http://wiki.rubyonrails.org/rails/pages/HowToRunBackgroundJobsInRails。我很想阅读有关这些工具的各种经验。

编辑4:

如果重要的话,我正在使用Passenger Phusion“modrails”。

编辑5:

我正在使用Windows Vista 64位开发机器;但是,我的生产机器是Ubuntu 8.04 LTS。我应该考虑为我的开发机器切换到Linux吗?这些解决方案是否适用于这两种方式?

14 个答案:

答案 0 :(得分:24)

Workling plugin允许您在队列中安排后台任务(他们将执行冗长的任务)。从版本0.3开始,您可以向工作人员询问其状态,这样您就可以显示一些漂亮的进度条。

Workling的另一个很酷的功能是可以切换异步后端:你可以使用DelayedJobs,Spawn(经典前叉),Starling ......

答案 1 :(得分:6)

我有一个非常大的网站,可以生成大量的大型CSV文件。这些有时需要几分钟才能完成。我做了以下事情:

  • 我有一个包含所请求文件详细信息的作业表。当用户请求文件时,请求进入该表,用户将进入“作业状态”页面,列出所有作业。
  • 我有一个rake任务,可以运行所有未完成的工作(作业模型上的类方法)。
  • 我在另一个处理这些工作的盒子上单独安装了rails。这个盒子只是做工作,外面的世界无法访问。
  • 在这个单独的框中,cron作业每60秒运行所有未完成的作业,除非作业仍在上次调用中运行。
  • 用户的作业状态页面自动刷新以显示作业的状态(在作业启动,运行,然后完成时由作业框更新)。作业完成后,结果文件会显示一个链接。

如果您计划一次只运行一个或两个,但是如果您想要扩展......可能会过于繁重......:)

答案 2 :(得分:4)

在后台调用./script/runner对我来说效果最好。 (我也在做PDF生成。)它似乎是最低的共同点,同时也是最简单的实现。 Here's a write-up of my experience

答案 3 :(得分:2)

不需要任何额外Gems或插件的简单解决方案是创建用于处理PDF生成的自定义Rake任务。您可以将PDF生成过程建模为状态机,其中包含提交处理完整等状态,这些状态存储在模型的数据库表中。对Rails应用程序的初始HTTP请求只是将一条记录添加到具有提交的状态的表中并返回。

将会有一个cron作业将您的自定义Rake任务作为单独的Ruby进程运行,因此主Rails应用程序不受影响。 Rake任务可以使用ActiveRecord查找具有提交状态的所有模型,将状态更改为处理,然后生成关联的PDF。最后,它应该将状态设置为完成。这使您在Rails应用程序中的AJAX调用能够监视PDF生成过程的状态。

如果您将Rake任务放在 your_rails_app / lib / tasks 中,那么它可以访问Rails应用程序中的模型。这种 pdf_generator.rake 的骨架如下所示:

namespace :pdfgenerator do
  desc 'Generates PDFs etc.'
  task :run => :environment do

    # Code goes here...
  end
end

如维基中所述,这种方法有一些缺点。你将使用cron定期创建一个相当重量级的Ruby进程,你的cron作业的时间需要仔细调整,以确保每个人有足够的时间在下一个进程之前完成。但是,这种方法很简单,可以满足您的需求。

答案 4 :(得分:2)

这看起来很旧。但是,我在我的应用程序中需要为不同的页面运行多个倒计时器,这就是使用 Ruby Thread 。即使页面被用户关闭,计时器也必须继续运行。

Ruby makes it easy to write multi-threaded programs with the Thread class. Ruby threads are a lightweight and efficient way to achieve parallelism in your code.我希望这能帮助其他想要获得背景的流浪者:他们应用中的并行/并发服务。同样,Ajax使得每秒调用特定的Rails [custom]操作变得更加容易。

答案 5 :(得分:1)

这确实听起来像你应该运行后台进程而不是应用程序实例(乘客/杂项,无论你使用哪个),因为你的应用程序可以保持做它应该做的事情,提供请求,同时某种背景任务,工作好,处理数字运算。我知道这并不涉及进步问题,但除非绝对必要,否则我认为这是一个很小的代价。

您可以让用户单击所需的操作,让该操作将请求传递给Workling队列,并让用户在完成后向用户发送某种通知,可能是电子邮件或其他内容。我不确定它的实用性,只是大声思考,但我的观点是,它似乎应该是某种背景任务。

答案 6 :(得分:1)

  

我正在使用Windows Vista 64位   开发机器;但是,我的   生产机器是Ubuntu 8.04 LTS。   我应该考虑切换到Linux   对于我的开发机器?请问   解决方案对两者都有效吗?

您是否考虑过在Vista上运行Linux?

答案 7 :(得分:1)

我建议使用Resque gem及其resque-status插件来处理繁重的后台进程。

Resque

  

Resque是一个Redis支持的Ruby库,用于创建后台作业,   将它们放在多个队列上,稍后再处理。

Resque状态

  

resque-status是提供的resque队列系统的扩展   简单的可追踪工作。

使用resque-status扩展程序在Resque worker上运行作业后,您将能够非常轻松地获取有关正在进行的进度和杀死特定进程的能力的信息。见例子:

status.pct_complete #=> 0
status.status #=> 'queued'
status.queued? #=> true
status.working? #=> false
status.time #=> Time object        
status.message #=> "Created at ..."

resque和resque-status还有一个很酷的网络界面,可以与您的工作进行互动,这非常酷。

答案 8 :(得分:0)

还有全新的Growl4Rails ...适用于此特定用例(以及其他用途)。

http://www.writebetterbits.com/2009/01/update-to-growl4rails.html

答案 9 :(得分:0)

我使用后台作业(http://codeforpeople.rubyforge.org/svn/bj/trunk/README)来安排任务。我正在构建一个小型管理站点,允许站点管理员运行各种各样的事情,我将从一个漂亮的Web界面从命令行运行。

答案 10 :(得分:0)

我知道你说你并不担心客户端,但我认为你可能会觉得这很有趣:Growl4Rails - 咆哮风格的通知是根据他们使用的例子来判断的。

答案 11 :(得分:0)

我之前使用过spawn,肯定会推荐它。

设置非常简单(许多其他解决方案都没有),并且效果很好。

答案 12 :(得分:0)

查看BackgrounDRb,它专为您所描述的场景而设计。

我认为它已经存在了一段时间并且非常成熟。您可以监控工人的状态。

在与生产环境相同的开发平台上进行开发是一个非常好的主意,尤其是在使用Rails时。在VM中运行Linux的建议是一个很好的建议。查看Sun xVM了解开源虚拟化软件。

答案 13 :(得分:0)

我个人使用active_messaging插件和activemq服务器(stomp或rest协议)。这对我们来说非常稳定,每个月处理数百万封邮件。