我们正在对一个新应用进行一些原型设计,并注意到其中一个动作需要永远加载(80-120秒)。由于很多处理不需要在页面加载时发生(我们可以通过Ajax稍后请求数据),我想到使用Process.fork
来允许页面立即返回,而处理仍然发生在“后面”场景。“
我们正在将Apache与Passenger一起用于该应用程序。
有几件事:
我了解delayed_jobs,resque,BJ和其他后台工作宝石。我们使用dj,最终也会使用类似的东西。在我们进行原型设计时,这是一个权宜之计。
我不关心服务器性能。该应用程序在自己的服务器上运行,只有少数用户尝试使用它。
早期测试表明这种方法效果很好,但我想知道使用它是否是个好主意。它会变得可靠吗?如果用户导航到另一个页面或关闭标签/浏览器,分叉过程是否会继续? fork完成后,进程是否会自行终止?
答案 0 :(得分:5)
取决于“处理”的含义。 通常,如果处理方式使用Rails堆栈,这将不可靠 - 因为请求释放的主进程可能被乘客分配给另一个请求,并且事情可能会出错。 此外,Passenger可能会在某些情况下关闭主进程,从而关闭Rails实例(减少空闲实例池等)。
通常,这可能会导致进程泄漏,意外锁定,竞争条件,关机时的应用程序错误等。
我建议使用在Apache / Passenger堆栈外运行的工作人员,例如使用群集BackgrounDRb或其他解决方案(您提到Resque)。
还有另一个想法,我目前用于我的应用程序的cron作业。对于长时间运行的任务,我的crontab只有少量wget
个动作。您可以根据需要使用OpenURI在ruby fork中执行类似的操作。想象一下HTTP应用程序 ping 本身。分叉进程不再需要Rails - 它只是访问任务页面,下一个Passenger服务请求并管理此特殊请求的应用程序实例。
如果Passenger杀死fork的父进程并因此分叉进程 - 另一个Rails实例应该继续处理http请求。
答案 1 :(得分:0)
是的,只要您使用之前经过测试和使用的宝石,它就是可靠的。 DelayedJobs和Spawn(我经常使用)已经存在很长时间了,应该完全符合你的期望。
由于进程在服务器后台运行,如果用户关闭没有客户端附件的选项卡/浏览器,它应该继续正常。当程序完成执行后,它将自行终止并释放内存。
您可以阅读有关这个优秀wiki-page分叉的更多信息。作为附注,不要在Rails中使用ruby fork方法,因为这对ActiveRecord不起作用。
答案 2 :(得分:0)
只是想加入,以防google让你来到这里。在乘客> 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最终会吃掉所有可用内存(正如我在生产系统中精心设计的那样)。显然,无法编程来拯救自己的生命。
希望这有帮助!