2011-11-04 15 views
6

usamos Rails y EventMachine juntos, y cuando usamos ese combo con Passenger hay una configuración muy específica que debe hacerse. Después de muchas pruebas y errores, obtuve la inicialización de EventMachine funcionando bien, pero me gustaría entender el código un poco mejor. Como puede ver a continuación en este fragmento de código, nuestro inicializador busca Pasajero, y luego verifica si se trata de un proceso bifurcado antes de reiniciar EventMachine.EventMachine y Ruby Threads: ¿qué está pasando realmente aquí?

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 

Mi pregunta está relacionada con la EM.reactor_running? y comandos EM.stop. Si Passenger ha bifurcado nuestro proceso, ¿por qué tengo que reiniciar la referencia de EM en un nuevo hilo? Si EM.reactor_running? devuelve verdadero, ¿a qué instancia de EM estoy haciendo referencia?

Puede ver el código de inicialización completa en nuestro blog aquí http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html

Respuesta

13

En primer lugar, hay sólo una instancia EventMachine por proceso Ruby, así que no importa lo que siempre referencia a la misma instancia de EM, independiente de la enhebre su actualmente.

Ejecuta el reactor en un hilo nuevo y separado para que no bloquee el hilo principal (cuyo propósito es servir a la solicitud web). EM.run de lo contrario tomaría el control, ingresando su ciclo de ejecución, sin dejar el bloque EM.run nunca más. EM.reactor_running? devuelve verdadero, bueno, si un bucle EM se está ejecutando en alguna parte. Como solo hay uno por proceso de Ruby, es bastante fácil para el método averiguar si EM se está ejecutando o no.

La configuración que tiene aquí es la forma más sencilla de usar EM dentro de un proceso Ruby normal sin interferir con todo lo demás que se está ejecutando. Supongo que está enviando mensajes a un agente de AMQP desde su aplicación web. Cada vez que envíe un mensaje, entrará en el bucle de ejecución de EM en el hilo separado, esa parte es bastante transparente para usted y no afectará al bucle principal, que puede seguir manejando la solicitud web de Rails. Sin embargo, tenga cuidado de insertar siempre las cosas en el ciclo EM con EM.next_tick. Intentar manejar sockets abiertos por EM en diferentes subprocesos podría ocasionar que sucedan cosas malas, lo que he visto en producción, por cierto al usar y crear una biblioteca llamada happening;)

Detener el ciclo EM antes de iniciar uno nuevo de un bucle EM que puede quedar de un proceso principal, lo que podría provocar problemas con los descriptores de archivos abiertos, utilizando EM, en el proceso principal. En el código personalizado esto se puede eludir utilizando EM.fork_reactor, pero como el proceso principal está fuera de su control, es más seguro verificar si existe un reactor y detenerlo antes de comenzar una nueva instancia.

+0

Gran descripción gracias. Tengo clara la necesidad de ejecutar EM en su propio hilo, pero cuando dices "EM loop que puede quedar", ahí es donde estoy un poco incierto. ¿Cómo se "sobra" un bucle EM? No estoy cerrando el proceso principal 'EM, ¿correcto? – Joshua

+0

Eso es exactamente lo que estás haciendo. Estás cerrando un EM potencialmente remanente del proceso principal. En caso de que se ejecute un bucle EM en el proceso principal, también se bifurcará, pero generalmente no le interesan en absoluto los descriptores de archivo que le quedan al padre, por lo que comienza desde el principio. Dado que es poco probable que el Pasajero ejecute un bucle EM por sí mismo, esta es más una medida de seguridad que cualquier otra cosa. – roidrage

+0

En una línea similar, estoy trabajando con RabbitMQ a través de la gema ruby-amqp, dentro de una aplicación websocket que se ejecuta en thin. Thin tiene su propio bucle de EventMachine, y actualmente estoy usando EventMachine.next_tick para entrar y hacer mis cosas de amqp. ¿Es correcto o debería usar EventMachine.fork_reactor para darle a AMQP su propio EM para usar? – wchrisjohnson

Cuestiones relacionadas