EventMachine and Ruby Threads - what's really going on here?

随声附和 提交于 2020-03-18 12:47:10

问题


we use Rails and EventMachine together, and when using that combo with Passenger there is some very specific setup that needs to be done. After a lot of trial and error, I got EventMachine initialization working well, but I would like to understand the code a little better. As you can see below in this code snippet, our initializer checks for Passenger, and then checks if it's a forked process before restarting 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

My question is related to the EM.reactor_running? and EM.stop commands. If Passenger has forked our process, why do I need to restart the EM reference in a new thread? If EM.reactor_running? returns true, what EM instance am I referencing?

You can see the full initializer code on our blog here http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html


回答1:


First of all, there's only one EventMachine instance per Ruby process, so no matter what you'll always reference the same EM instance, independent of the thread your currently in.

You run the reactor in a new, separate thread so that it doesn't block the main thread (whose purpose it is to serve the web request). EM.run would otherwise take over control, entering its run loop, not leaving the EM.run block anymore. EM.reactor_running? returns true, well, if an EM loop is running somewhere. As there is only one per Ruby process it's easy enough for the method to figure out if EM is running or not.

The setup you have here is the simplest way to use EM inside a normal Ruby process without interfering with everything else that's running. I'm assuming you're pushing messages to an AMQP broker from your web app. Whenever you send a message, it will go into EM's run loop in the separate thread, that part is pretty transparent to you, and not affect the main loop, which can continue handling the Rails web request. Be careful though to always push things onto the EM loop using EM.next_tick. Trying to handle sockets opened by EM in different threads could result in bad things happening, which I have seen in production, incidentally by using and building a library called happening ;)

Stopping the EM loop before starting a new one takes care of an EM loop that may be left over from a parent process, which could result in problems with file descriptors opened, using EM, in the parent process. In custom code this can be circumvented by using EM.fork_reactor, but as the parent process is out of your control, it's safest to check if a reactor exists and stop it before starting a new instance.



来源:https://stackoverflow.com/questions/8016537/eventmachine-and-ruby-threads-whats-really-going-on-here

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!