2010-10-21 73 views
4

我们正在做一些新应用的原型设计,并注意到其中一项操作需要永久加载(80-120秒)。由于很多处理不需要在页面加载时发生(我们可以稍后通过Ajax请求数据),所以我想使用Process.fork来允许页面立即返回,而处理仍然在“幕后”进行。Rails控制器中的Process.fork

我们使用Apache与Passenger为应用程序。

几件事情:

  1. 我知道delayed_jobs,resque,BJ等后台作业的宝石。我们使用dj,并且最终会使用类似的东西来实现这一点。这是我们原型设计时的权宜之计。

  2. 我不关心服务器的性能。该应用程序运行在自己的服务器上,只有少数用户试用它。

早期测试表明这很好,但我想知道这是否是一个好主意。它会变得可靠吗?如果用户导航到另一个页面,或者关闭标签页/浏览器,分叉过程是否会继续? fork完成后,进程是否会自行终止?

回答

5

取决于“处理”的含义。 一般来说,如果处理意味着使用Rails堆栈,这并不可靠 - 因为由请求释放的主进程可能会被乘客分配给另一个请求,并且事情可能会出错。 此外,Passenger可能会在某些情况下关闭主进程并因此关闭Rails实例(减少空闲实例池等)。

一般来说,这可能会导致进程泄漏,意外锁,竞争条件,应用程序错误而停机等

我建议使用Apache /客运栈外运行工人,例如使用集群BackgrounDRb或其他解决方案(您提到Resque)。

还有一个想法,我目前使用我的应用程序的cron作业。我的crontab只有几个wget来处理长时间运行的任务。您可以按需要在红宝石叉子上做类似OpenURI的事情。想象一下应用程序通过HTTP pinging本身。分叉进程不再需要Rails - 它只是访问任务页面,然后Passenger为此特殊请求提供服务请求并管理应用程序实例。

如果乘客杀死了fork的父代并因此分叉进程 - 另一个Rails实例应该继续处理http请求。

+0

很好的答案,谢谢。这是我正在寻找的信息 - 我对乘客查杀过程感到好奇等等。问题是,在我们进行原型设计时,我不想花费大量的时间或精力设置后台处理。虽然我们最终会使用DJ,BackgrounDRb,Resque或类似的技术,但在这种情况下它们都是过度的。我只想返回页面,同时执行一个单一的模型动作,用数据填充一些数据库表。 – vonconrad 2010-10-21 12:38:46

+0

我用另一个想法编辑了答案。 – gertas 2010-10-24 18:34:36

0

是的,只要您使用之前已经过测试和使用的宝石,它就是可靠的。 DelayedJobs和Spawn(我经常使用)都已经存在了相当长的一段时间,应该完全按照你期望的那样去做。

由于该过程在服务器的后台运行,因此如果用户关闭了没有客户端附件的选项卡/浏览器,它应该会继续良好。当程序完成执行时,它将自行终止并释放内存。

你可以阅读更多关于分叉这个优秀wiki-page。作为一个侧面说明,不要在Rails中使用ruby fork方法,因为这对ActiveRecord并不会很好。

+0

恐怕你没有真的看过我的问题......我知道DJ,Spawn和其他宝石,但是如果我们能够在原型制作的时候想避免使用它们,我特别要指出的是,只是使用'Process.fork'会导致问题 - 本质上是在最后一段中将您的“旁注”作为您答案的要点。你想介绍一下吗? – vonconrad 2010-10-21 12:32:34

+1

我可能没有得到它,但产卵需要没有实现;你唯一要做的就是调用spawn并给它一个在后端执行的块。这几乎不会花费你几个小时的时间。分叉的问题在于,据我所知,ActiveRecord在分叉中不可用。我不知道技术细节,但这就是为什么Spawn被创建与其他代码分离的原因。 – Maran 2010-10-22 11:44:19

0

只是想编钟,以防谷歌把你带到这里。在Passenger> v4.0中,有一种方法可以通过使用“带外工作”来实现。我用它长长的任务,比如像这样在西纳特拉控制器发送电子邮件:

# Your app should tell Passenger about this OOB task, won't run otherwise 
headers['X-Passenger-Request-OOB-Work'] = "true" 
PhusionPassenger.on_event(:oob_work) do 
    # The following line takes a while to run, 
    # but won't tie up any http-serving processes 
    mail.deliver! 
end 

的信息可以在这里找到:http://blog.phusion.nl/2013/01/22/phusion-passenger-4-technology-preview-out-of-band-work/

以前,我一直在使用Process.fork试了又试杀死进程后来;虽然这实际上完成了第一部分,但事实上它并不会真正杀死分叉进程,而乘客最终会吃掉所有可用的内存(正如我在生产系统中精心设计的)。显然,无法编程来拯救我自己的生活。

希望这会有所帮助!