我们一起使用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上查看完整的初始化代码
解决方法
首先,每个Ruby进程只有一个EventMachine实例,所以无论你总是引用相同的EM实例,都独立于你当前的线程.
您在一个新的,单独的线程中运行reactor,以便它不会阻塞主线程(其目的是为Web请求提供服务).否则,EM.run将接管控制,进入其运行循环,不再离开EM.run块. EM.reactor_running?如果EM循环在某处运行,则返回true.由于每个Ruby进程只有一个,因此该方法很容易确定EM是否正在运行.
这里的设置是在普通Ruby进程中使用EM而不干扰正在运行的其他所有内容的最简单方法.我假设你正在从你的网络应用程序向AMQP经纪人推送消息.无论何时发送消息,它都将进入单独线程中的EM运行循环,该部分对您来说非常透明,并且不会影响主循环,主循环可以继续处理Rails Web请求.但要注意使用EM.next_tick始终将内容推送到EM循环中.尝试在不同的线程中处理由EM打开的套接字可能会导致不好的事情发生,我在生产中看到了这种情况,顺便说一下,使用并构建了一个名为occurrence的库;)
在开始新循环之前停止EM循环会处理可能从父进程遗留的EM循环,这可能导致在父进程中使用EM打开文件描述符的问题.在自定义代码中,这可以通过使用EM.fork_reactor来规避,但由于父进程不受您的控制,因此最安全的方法是检查反应器是否存在并在启动新实例之前将其停止.