Как создать EventMachine внутри приложения Rails?

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

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

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

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


person Mike Trpcic    schedule 27.04.2011    source источник


Ответы (8)


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

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

person Jonah    schedule 27.04.2011

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

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

person tadman    schedule 27.04.2011
comment
Что значит побочный процесс? Вы имеете в виду, что вы порождаете процесс в файле инициализатора? - person Donato; 14.09.2016
comment
@Donato Я имею в виду, что вам нужно поддерживать независимый процесс, обычно используя что-то вроде Daemons для создания фоновых процессов и средства запуска процессов. например Eye, чтобы он продолжал работать. - person tadman; 14.09.2016
comment
Мне не нравятся демоны, потому что ими приходится управлять отдельно от приложения Rails. Я хочу, чтобы Passenger использовал свой процесс Preloader для разветвления нового процесса (используя семантику копирования при записи ruby ​​2 и, таким образом, используя пространство общей памяти) в инициализаторе, и я хочу, чтобы этот новый процесс управлялся Passenger. Я хочу, чтобы этот процесс опрашивал IMAP, используя бездействие, но имея доступ к среде Rails. Я хочу использовать EventMachine, потому что будет много бездействия и не хочется тратить ресурсы памяти на отдельные стеки потоков. - person Donato; 14.09.2016
comment
По сути, я просто хочу знать, как разветвить этот отдельный процесс Passenger в инициализаторе и запустить EventMachine в этом новом процессе. - person Donato; 14.09.2016
comment
То, что вам нравится, и то, как вы решаете эту проблему, кажется, здесь расходятся. Passenger может убить ваш процесс Rails, если с трафиком ничего не происходит, что он будет делать. Это означает, что во время простоя у вас нет фоновых процессов. Вам нужно что-то внешнее от Rails, чтобы продолжать работать, и лучший план для этого — независимый процесс, неподконтрольный Passenger. Надежда на то, что ваш процесс Passenger не будет убит, или предотвращение того, что Passenger сделает это, будет не чем иным, как проблемой. - person tadman; 14.09.2016

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

Например:

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

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

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

person Eduardo Aceituno    schedule 02.12.2011
comment
Спасибо, этот совет действительно помог мне с приложением для тонких рельсов! - person OzBandit; 24.10.2012

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

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

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

person Christian Fazzini    schedule 27.04.2011

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

ОБНОВИТЬ

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

person Joshua    schedule 04.11.2011

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

Поддержка стоечных промежуточных программ + Rainbows! и тонкие веб-серверы

person John K. Chow    schedule 23.03.2012
comment
К сожалению, этот сайт не работает, а Cramp заброшен. Кое-что рассмотреть, приближаясь к этой проблеме сегодня. - person tadman; 14.09.2016

Вам, вероятно, не следует больше использовать 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 on rails
  3. заметка на будущее, следите за целлулоидным сообществом, оттуда приходят интересные распределенные решения https://github.com/celluloid/reel/wiki/WebSockets, https://github.com/celluloid/dcell
  4. ?
person bbozo    schedule 24.12.2013

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

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

person hlcs    schedule 13.12.2016