Rails控制器中的Process.fork

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

我们正在将Apache与Passenger一起使用。

有几件事:

  1. 我知道delayed_jobs,resque,BJ和其他后台工作gem。 我们使用dj,最终也会使用类似的东西。 在我们进行原型设计时,这是一个权宜之计。

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

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

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

通常,这可能会导致过程泄漏,意外锁定,竞争条件,关闭时应用程序错误等。

我建议使用在Apache / Passenger堆栈外运行的工作程序,例如使用集群BackgrounDRb或其他解决方案(你提到Resque)。

还有另一个想法,我目前用于我的应用程序的cron作业。 我的crontab只是很少用于长时间运行任务的操作。 您可以根据需要使用OpenURI在ruby fork中执行类似的操作。 想象一下应用程序通过HTTP ping自己。 分叉进程不再需要Rails – 它只访问任务页面和下一个Passenger服务请求并管理此特殊请求的应用程序实例。

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

是的,只要您使用之前经过测试和使用过的gem,它就是可靠的。 DelayedJobs和Spawn(我经常使用)已经存在了很长时间,应该完全符合您的预期。

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

您可以在这个出色的维基页面上阅读更多关于分叉的信息。 作为附注,不要在Rails中使用ruby fork方法,因为这对ActiveRecord不起作用。

只是想加入,以防谷歌让你到这里。 在Passenger> v4.0中,有一种方法可以通过使用“带外工作”来实现这一目标。 我将它用于冗长的任务,例如在Sinatra控制器中发送电子邮件,如下所示:

 # 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并试图在以后杀死该进程; 虽然这实际上是第一部分,但它实际上并不会在之后杀死分叉进程,并且Passenger最终将占用所有可用内存(正如我在生产系统中精心设计的那样)。 显然,不能编程来拯救我自己的生命。

希望这可以帮助!