Как вы создаете EventMachine «внутри» приложения Rails? - PullRequest
20 голосов
/ 27 апреля 2011

У меня есть приложение Rails, и я хочу добавить в него какую-то поддержку WebSocket. Судя по различным поискам, кажется, что лучшее решение WebSocket на основе Ruby - em-websocket , работающее на EventMachine.

Мне было интересно, есть ли способ "интегрировать" реактор EventMachine в Rails? Где я могу разместить код инициализации? Это правильный способ сделать это?

Я видел этот пример, который обращается к Синатре для выполнения запроса EventMachine GET, но это не совсем то, что я ищу.

Любая помощь приветствуется.

Ответы [ 8 ]

9 голосов
/ 27 апреля 2011

Вы не можете запустить механизм Eventmachine внутри самого Rails, так как это постоянный цикл выполнения, который навсегда заблокирует один из ваших процессов Rails. Обычно это побочный процесс, использующий Eventmachine, и Rails связывается с ним через сокеты для отправки уведомлений.

Джаггернаут служит примером такого рода вещей, где он реализует клиент Websocket и хук Rails для отправки ему уведомлений. С тех пор проект отказался от версии Ruby в пользу версии JavaScript Node.js, но это все еще служит очень подробным примером того, как можно использовать Eventmachine.

6 голосов
/ 02 декабря 2011

Если вы запускаете приложение rails на тонком сервере (bundle exec thin start), тонкий сервер запускает EventMachine для вас, и тогда ваше приложение rails может выполнять код EM везде, где вам нужно.

Например:

Библиотека или инициализатор с этим кодом:

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

не блокирует применение процессов рельсов.

5 голосов
/ 27 апреля 2011

Не знаю, если это то, что вы после.Но если вы хотите предоставить какую-нибудь систему обмена сообщениями с сокетами.

Посмотрите на Faye .Он предоставляет серверы сообщений для Node.js и Rack.Существует также рельсов, отлитых для этого Райаном Бейтсом, что должно упростить реализацию.

Надеюсь, это поможет.

4 голосов
/ 04 ноября 2011

Я потратил немало времени на изучение этого вопроса.EventMachine должен запускаться как поток в вашей установке rails (если вы не используете Thin,), и для Пассажира есть некоторые особые соображения.Я написал нашу реализацию здесь: http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html

ОБНОВЛЕНИЕ

Мы вытащили эту конфигурацию в драгоценный камень под названием Мгновенно.Источник здесь https://github.com/eatenbyagrue/momentarily

2 голосов
/ 23 марта 2012

Я бы рассмотрел Судорога . Это асинхронный фреймворк, построенный на основе EventMachine и поддерживающий тонкий сервер:

Rack Middlewares поддержка + Радуга! и Тонкие веб-серверы

2 голосов
/ 27 апреля 2011

Я бы попробовал использовать em-synchrony , чтобы запустить реактор в волокне. В приложении rails вы, вероятно, можете запустить его в инициализаторе, поскольку кажется, что вы просто хотите оставить реактор включенным, чтобы отвечать на запросы веб-сокетов. Как следует из других ответов, я думаю, что вы хотите либо настроить соединение сокетов с вашим реактором, либо использовать одного из асинхронных клиентов для хранилища данных, из которого ваш реактор и код rails могут считывать и записывать данные для обмена данными.

Некоторые из моих коллег собрали несколько примеров запуска EM-реакторов по запросу в коде ruby ​​для запуска своих тестов в EventMachine. Я бы попробовал использовать это в качестве возможного примера; грабли и тестирование на eventmachine

0 голосов
/ 13 декабря 2016

У меня была такая же проблема, и я нашел решение.Сначала поместите ваш код в lib dir (например, /lib/listener/init.rb) и создайте один метод класса, который запускает EM, например 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

После этого я использовал dante драгоценный камень.Создайте /init/listener файл.Код может быть таким:

#!/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

Теперь вы можете запустить свой код так: ./bin/listener start, ./bin/listener restart, ./bin/listener stop

Вы можете использовать бог для мониторинга вашего слушателя работает.Но убедитесь, что вы используете тот же файл pid (/tmp/listener.pid).

0 голосов
/ 24 декабря 2013

Вам, вероятно, не стоит больше использовать EM, если вы можете помочь ему, кажется, что он больше не поддерживается - если вы столкнулись с ошибкой - вы сами.

Большинство ответов вышене работают в JRuby из-за https://github.com/eventmachine/eventmachine/issues/479, а именно:

Thread.new{ EM.run }

, используемый EM::Synchrony, и различные ответы, найденные в Интернете (такие как EventMachine и Ruby Threads- что на самом деле здесь происходит? ) нарушены при реализации механизма событий JRuby (волокна - это потоки в jruby, и в настоящее время нет никакой схемы, когда это изменится).

Параметры обмена сообщениями JRuby будут

  1. развертывание с TorqueBox (поставляется в комплекте с HornetQ), http://torquebox.org/news/2011/08/15/websockets-stomp-and-torquebox/, впечатляюще и по-корпоративному, но не слишком элегантно, если вы не из Java-фона
  2. более новые версии Faye должны работатьс JRuby, Faye в jruby на рельсах
  3. заметка на будущее, следите за целлулоидным сообществом, некоторые интересные распределенные решения приходят сюдам там https://github.com/celluloid/reel/wiki/WebSockets, https://github.com/celluloid/dcell
  4. ?
...