我们一起使用 Rails 和 EventMachine,当将该组合与 Passenger 一起使用时,需要完成一些非常具体的设置。经过大量的试验和错误,我的 EventMachine 初始化运行良好,但我想更好地理解代码。正如您在下面的代码片段中看到的,我们的初始化程序会检查 Passenger,然后在重新启动 EventMachine 之前检查它是否是分叉进程。
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
# for passenger, we need to avoid orphaned threads
if forked && EM.reactor_running?
EM.stop
end
Thread.new {
EM.run do
我的问题与 EM.reactor_running 有关?和 EM.stop 命令。如果 Passenger 已经分叉了我们的进程,为什么我需要在新线程中重新启动 EM 引用?如果 EM.reactor_running?返回 true,我引用哪个 EM 实例?
您可以在我们的博客上查看完整的初始化程序代码http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html
首先,每个 Ruby 进程只有一个 EventMachine 实例,因此无论发生什么情况,您都将始终引用相同的 EM 实例,而与当前所在的线程无关。
您在一个新的单独线程中运行反应器,这样它就不会阻塞主线程(其目的是服务 Web 请求)。否则 EM.run 将接管控制权,进入其运行循环,不再离开 EM.run 块。 EM.reactor_running?如果 EM 循环正在某处运行,则返回 true。由于每个 Ruby 进程只有一个,因此该方法很容易确定 EM 是否正在运行。
您此处的设置是在普通 Ruby 进程中使用 EM 的最简单方法,而不会干扰正在运行的其他所有内容。我假设您正在从 Web 应用程序将消息推送到 AMQP 代理。每当您发送消息时,它都会进入单独线程中的 EM 运行循环,这部分对您来说非常透明,并且不会影响主循环,主循环可以继续处理 Rails Web 请求。但要小心,始终使用 EM.next_tick 将事物推入 EM 循环。尝试在不同线程中处理 EM 打开的套接字可能会导致发生不好的事情,我在生产中看到过这种情况,顺便使用和构建了一个名为“发生”的库;)
在开始新循环之前停止 EM 循环可以处理父进程中可能遗留下来的 EM 循环,这可能会导致在父进程中使用 EM 打开的文件描述符出现问题。在自定义代码中,可以使用 EM.fork_reactor 来规避此问题,但由于父进程不受您的控制,因此最安全的做法是检查反应器是否存在并在启动新实例之前停止它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)