Как вы создаете EventMachine "внутри" приложения Rails?
У меня есть приложение Rails, и я хочу добавить к нему какую-то поддержку WebSocket. Из разных поисковых запросов, похоже, лучшее решение на основе Ruby на базе WebSocket em-websocket работает в EventMachine.
Мне было интересно, есть ли способ "интегрировать" EventMachine в Rails? Где я могу поставить код инициализации? Правильно ли это удается?
Я видел этот пример, который возвращается на Sinatra для выполнения запроса EventMachine GET
, но это не совсем то, что я Я ищу.
Любая помощь приветствуется.
Ответы
Ответ 1
Я попробую использовать em-synchrony, чтобы запустить реактор в волокне. В приложении rails вы, вероятно, можете запустить его в инициализаторе, так как кажется, что вы просто хотите покинуть реактор, чтобы отвечать на запросы websocket. Как было предложено в других ответах, я думаю, что вы хотите либо установить связь сокета с вашим реактором, либо использовать один из асинхронных клиентов в хранилище данных, которое и ваш код реакторов и рельсов может считывать и записывать для обмена данными.
Некоторые из моих коллег собрали несколько примеров запуска реактивных реакторов EM по запросу в рубиновом коде для запуска своих тестов в EventMachine. Я бы попытался использовать это как возможный пример; сгребать и тестировать с помощью eventmachine
Ответ 2
Вы не можете запустить движок Eventmachine внутри самого Rails, так как это постоянный цикл цикла, который будет блокировать один из ваших Rails-процессов навсегда. Обычно выполняется боковой процесс, который использует Eventmachine и Rails для связи с ним через сокеты для отправки уведомлений.
Juggernaut служит примером такого рода вещей, когда он реализует клиент Websocket и крючок Rails для отправки ему уведомлений. Проект с тех пор не одобряет версию Ruby в пользу версии JavaScript Node.js, но это все еще служит очень подробным примером того, как можно использовать Eventmachine.
Ответ 3
Если вы запускаете приложение rails на тонком сервере (тонкий запуск пуска exec), то на вашем сервере используется EventMachine, а затем ваше приложение rails может выполнять EM-код везде, где вам нужно.
Пример:
Библиотека o инициализатор с этим кодом:
EM.next_tick do
EM.add_periodic_timer(20) do
puts 'from Event Machine in rails code'
end
end
не блокирует процесс обработки рельсов.
Ответ 4
Не знаю, если это то, что вам нужно. Но если вы хотите предоставить некоторую систему сокетов-сообщений,
Посмотрите Faye. Он предоставляет серверы сообщений для Node.js и Rack. Существует также rails cast для этого Райана Бейтса, который должен упростить реализацию.
Надеюсь, что это поможет.
Ответ 5
Я потратил немало времени на изучение этого. EventMachine нужно запускать как поток в ваших рельсах (если вы не используете Thin), и есть несколько особых соображений для Passenger. Я написал нашу реализацию здесь: http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html
ОБНОВЛЕНИЕ
Мы вытащили эту конфигурацию в драгоценный камень под названием Momentently. Источник находится здесь https://github.com/eatenbyagrue/momentarily
Ответ 6
Я рассмотрю Cramp. Это асинхронная структура, построенная поверх EventMachine, и поддерживает тонкий сервер:
Поддержка Rack Middlewares + Rainbows! и тонкие веб-серверы
Ответ 7
Вероятно, вам больше не нужно использовать EM, если вы можете помочь ему, кажется, больше не поддерживаются - если вы столкнулись с ошибкой - вы сами.
Большинство ответов выше не работают в JRuby из-за https://github.com/eventmachine/eventmachine/issues/479 - а именно:
Thread.new{ EM.run }
используемый EM::Synchrony
, и различные ответы, найденные в Интернете (например, EventMachine и Ruby Threads - что действительно происходит здесь?) нарушены при реализации события JRuby eventmachine (волокна являются нитями в jruby и в настоящее время нет дорожной карты, когда это изменится).
Параметры обмена сообщениями JRuby будут
Ответ 8
У меня была такая же проблема и найденное решение. Сначала введите код 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 gem. Создайте файл /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
Вы можете использовать god для мониторинга работы вашего слушателя. Но убедитесь, что вы используете один и тот же файл pid (/tmp/listener.pid
).