ruby-on-rails - 使用 Kernel#fork 进行后台进程,专业人士?缺点?

标签 ruby-on-rails ruby background delayed-job backgroundrb

我想知道使用 fork{} 从 Rails 应用程序“后台”处理是否是个好主意...

从我收集到的 fork{my_method; Process#setsid} 实际上做了它应该做的事情。

1) 创建另一个具有不同 PID 的进程

2) 不中断调用过程(例如它继续 w/o 等待 fork 完成)

3) 执行子进程直到它完成

..这很酷,但这是个好主意吗? fork到底在做什么?它会在内存中创建我的整个 rails mongrel/passenger 实例的重复实例吗?如果是这样那就太糟糕了。或者,它是否以某种方式在不消耗大量内存的情况下完成。

我的最终目标是取消我的后台守护进程/队列系统,转而支持这些进程的 fork (主要是发送电子邮件)——但如果这不能节省内存,那么它肯定是朝着错误的方向迈出了一步

最佳答案

fork 确实会复制您的整个流程,并且根据您连接到应用程序服务器的方式,还会复制一份。正如在其他讨论中指出的那样,这是通过写时复制 完成的,因此这是可以容忍的。毕竟,Unix 是围绕 fork(2) 构建的,因此它必须相当快地管理它。请注意,还会复制任何部分缓冲的 I/O、打开的文件和许多其他内容,以及 Spring 加载以写出它们的程序状态,这是不正确的。

我有几点想法:

  • 您在使用 Action Mailer 吗?似乎电子邮件可以通过 AM 或 Process.popen 等方式轻松完成。 (Popen 将进行一次 fork ,但紧随其后的是 exec。)
  • 通过执行另一个 ruby​​ 解释器的 Process.exec 以及您的功能,立即摆脱所有这些状态。如果要传输的状态太多,或者您确实需要使用那些重复的文件描述符,您可能会执行类似 IO#popen 的操作,这样您就可以将子进程的工作发送出去。系统会自动将包含子进程Ruby解释器文本的页面分享给父进程。
  • 除了上述之外,您可能还需要考虑使用 daemons gem。虽然您的 rails 进程已经是一个守护进程,但使用 gem 可以更轻松地保持一个后台任务作为批处理作业服务器运行,并使其易于启动、监视、在它崩溃时重新启动以及在您这样做时关闭。 .
  • 如果您确实从 fork(2)ed 子进程中退出,请使用 exit! 而不是 exit
  • 像您一样设置好消息队列和守护进程,这对我来说是个不错的解决方案:-)

关于ruby-on-rails - 使用 Kernel#fork 进行后台进程,专业人士?缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1568176/

相关文章:

r - 根据数据集中的另一个变量设置背景颜色

css - 多个背景图片定位

heroku 中的 CSS 中断

ruby-on-rails - 如何在 Rails 中获取随机记录?

ruby-on-rails - 如果我的模型不代表不同的想法,而是代表具有重叠字段的不同类型,我应该在应用程序中使用什么数据库?

ruby - 将 Ruby DateTime 字符串转换为毫秒

ruby-on-rails - 'roo' 中 Excel 未初始化常量中的名称错误

ruby-on-rails - 如何访问哈希中的嵌套键

python - python BeautifulSoup 库的 ruby​​ 等价物是什么?

html - 当我尝试重复 x 图像 Sprite 时,它会显示整个图像