ruby-on-rails ruby ruby-on-rails-3 websocket eventmachine

ruby on rails - ¿Cómo se genera un EventMachine "dentro" de una aplicación Rails?



ruby-on-rails ruby-on-rails-3 (8)

Tengo una aplicación Rails y estoy buscando agregarle algún tipo de soporte WebSocket. De varias búsquedas en Google, parece que la mejor solución WebSocket basada en Ruby es em-websocket ejecuta en EventMachine.

Me preguntaba si habría una manera de "integrar" un reactor EventMachine en Rails? ¿Dónde pongo el código de inicialización? ¿Es esta la forma correcta de lograr esto?

He visto this ejemplo que recurre a Sinatra para hacer una solicitud GET EventMachine, pero no es exactamente lo que estoy buscando.

Cualquier ayuda es apreciada.


Consideraría mirar Cramp . Es un marco asíncrono construido sobre EventMachine y es compatible con el servidor Thin:

Soporte de Rack Middlewares + Arcoiris! y servidores web delgados


Intentaría usar em-synchrony para iniciar un reactor en una fibra. En una aplicación de rieles, probablemente puedas iniciarlo en un inicializador, ya que parece que solo quieres dejar el reactor en marcha para responder a las solicitudes de websocket. Tal como lo sugieren las otras respuestas, creo que desea configurar la comunicación de socket con su reactor o usar uno de los clientes asíncronos para un almacén de datos en el que tanto el código de su reactor como el de los rieles pueden leer y escribir para intercambiar datos.

Algunos de mis compañeros de trabajo reunieron algunos ejemplos de reactores EM de arranque bajo demanda en código ruby ​​para ejecutar sus pruebas dentro de EventMachine. Intentaría usar eso como un posible ejemplo; rastrillar y probar con eventmachine


No puede ejecutar el motor de Eventmachine dentro de Rails ya que es un ciclo de ejecución persistente que bloquearía uno de sus procesos de Rails de forma permanente. Lo que generalmente se hace es que hay un proceso lateral que utiliza Eventmachine y Rails se comunica con él a través de sockets para enviar notificaciones.

Juggernaut sirve como un ejemplo de este tipo de cosas en las que implementa un cliente Websocket y un gancho Rails para enviarle notificaciones. Desde entonces, el proyecto ha desaprobado la versión de Ruby a favor de una versión de JavaScript Node.js, pero esto todavía sirve como un ejemplo muy completo de cómo se puede usar Eventmachine.


No sé si esto es lo que estás buscando. Pero si desea proporcionar algún tipo de sistema de mensajería de socket.

Echa un vistazo a Faye . Proporciona servidores de mensajes para Node.js y Rack. También hay una lista de rieles para esto por Ryan Bates que debería simplificar la implementación.

Espero que ayude.



Probablemente no deberías usar EM más si puedes evitarlo, parece que ya no se mantiene. Si te encuentras con un error, estás solo.

La mayoría de las respuestas anteriores no funcionan en JRuby debido a https://github.com/eventmachine/eventmachine/issues/479 , es decir, el patrón:

Thread.new{ EM.run }

utilizado por EM::Synchrony y varias respuestas encontradas en Internet (como EventMachine y Ruby Threads - ¿qué está pasando aquí? ) se rompen bajo la implementación de JRuby eventmachine (las fibras son hilos en jruby y actualmente no hay una hoja de ruta para cuando esto cambie) ).

Las opciones de mensajería de JRuby serían

  1. implemente con TorqueBox (que viene con HornetQ), http://torquebox.org/news/2011/08/15/websockets-stomp-and-torquebox/ , impresionante y emprendedor pero no realmente elegante a menos que venga de un Fondo de Java
  2. las nuevas versiones de Faye deberían funcionar con JRuby, Faye en jruby sobre rieles
  3. nota para el futuro, vigile la comunidad de celuloides, algunas soluciones distribuidas interesantes provienen de allí https://github.com/celluloid/reel/wiki/WebSockets , https://github.com/celluloid/dcell
  4. ?

Si ejecuta la aplicación rails en un servidor ligero (bundle exec thin start), el servidor delgado ejecuta EventMachine para usted y luego su aplicación rails puede ejecutar el código EM donde lo necesite.

Por ejemplo:

Una biblioteca o inicializador con ese código:

EM.next_tick do EM.add_periodic_timer(20) do puts ''from Event Machine in rails code'' end end

No bloquea los rieles de los procesos de aplicación.


Tuve el mismo problema y encontré solución. Primero, ponga su código en lib dir (por ejemplo, /lib/listener/init.rb ) y cree un método de clase que ejecute EM, por ejemplo, Listener.run .

#!/usr/bin/env ruby require File.expand_path(''../../config/environment'', File.dirname(__FILE__)) class Listener def self.run # your code here # you can access your models too end end

Después de eso usé la gema dante . Crear un archivo /init/listener . El código puede ser así:

#!/usr/bin/env ruby require File.expand_path(''../../lib/listener/init.rb'', __FILE__) log_file = File.expand_path(''../../log/listener.stdout.log'', __FILE__) pid_file = File.expand_path(''../../tmp/listener.pid'', __FILE__) listener = Dante::Runner.new(''listener'') if ARGV[0] === ''start'' listener.execute(daemonize: true, pid_path: pid_file, log_path: log_file) { Listener.run } elsif ARGV[0] === ''restart'' listener.execute(daemonize: true, restart: true, pid_path: pid_file, log_path: log_file) { Listener.run } elsif ARGV[0] === ''stop'' listener.execute(kill: true, pid_path: pid_file) end

Ahora puede ejecutar su código así: ./bin/listener start , ./bin/listener restart , ./bin/listener stop

Puedes usar a god para controlar que tu oyente se está ejecutando. Pero asegúrese de usar el mismo archivo pid ( /tmp/listener.pid ).