EventMachine和Ruby Threads - 这里到底发生了什么?

时间:2011-11-04 22:40:41

标签: ruby-on-rails ruby eventmachine

我们一起使用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

上查看完整的初始化代码

1 个答案:

答案 0 :(得分:13)

首先,每个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打开的套接字可能会导致不好的事情发生,我在生产中看到了这种情况,顺便说一下,使用并构建了一个名为events的库;)

在开始新循环之前停止EM循环会处理可能从父进程遗留的EM循环,这可能导致在父进程中使用EM打开文件描述符的问题。在自定义代码中,这可以通过使用EM.fork_reactor来规避,但由于父进程不受您的控制,最安全的方法是检查反应堆是否存在并在启动新实例之前将其停止。