2011-11-04 76 views
6

我们一起使用Rails和EventMachine,并且在与Passenger一起使用该组合时,需要完成一些非常特定的设置。经过大量的试验和错误之后,我的EventMachine初始化工作正常,但我想更好地理解代码。正如你在下面的代码片段中看到的,我们的初始化器检查Passenger,然后在重新启动EventMachine之前检查它是否是分叉进程。EventMachine和Ruby线程 - 这里究竟发生了什么?

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

回答

13

首先充分初始化代码,还有每个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来规避,但由于父进程不在您的控制范围内,因此检查一个反应堆是否存在并在开始新实例之前停止它是最安全的。

+0

很好的描述谢谢。我清楚需要在自己的线程中运行EM,但是当你说“可能剩下的EM回路”时,这就是我不清楚的地方。 EM循环如何“遗留”?我没有关闭父进程'EM,对吗? – Joshua

+0

这正是你在做的。您正在关闭可能遗留在父进程中的EM。如果一个EM循环运行在父进程中,它也会被分叉,但是你通常不关心父进程剩下的文件描述符,所以你需要从头开始。鉴于Passenger不太可能独立运行EM环路,这比其他任何安全措施都更重要。 – roidrage

+0

与此类似,我正在通过ruby-amqp gem与RabbitMQ一起工作,在一个websocket应用程序内运行。瘦有它自己的EventMachine循环,我目前正在使用EventMachine.next_tick打破并做我的amqp的东西。这是正确的,或者我应该使用EventMachine.fork_reactor给AMQP它自己的EM使用? – wchrisjohnson