Запуск EventMachine в новом потоке после загрузки Rails с использованием Thin
У меня есть приложение Rails 3.2, работающее на тонком сервере, и в application.rb я хочу запустить EventMachine:
# application.rb
config.after_initialize do
if ENV['EM']
EM.run do
host = '0.0.0.0'
port = 3001
# hit Ctrl + C to stop
Signal.trap("INT") { EventMachine.stop }
Signal.trap("TERM") { EventMachine.stop }
EventMachine::start_server host, port, SomeModule
puts "EventMachine running on #{host}:#{port}. Ctrl + C to stop."
end
end
end
SomeModule имеет код, который зависит от загружаемых Rails. Вот почему я помещаю это в блок after_initialize вместо инициализатора.
Теперь, когда я запускаю свой сервер (с rails s
) мой вывод выглядит нормально:
=> Booting Thin
=> Rails 3.2.13 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
EventMachine running on 0.0.0.0:3001. Ctrl + C to stop.
Но когда я захожу на localhost в моем браузере, я получаю 204 No Content
ответ.
Я могу думать о нескольких вещах, которые вызывают это, но не решение:)
- Возможно, я запускаю EventMachine в том же потоке, который блокирует приложение Rails. Но Тонкий должен справиться с этим правильно?
- Может быть, я должен запустить свой сервер по-другому, но как тогда?
2 ответа
После еще одного поиска в Google я обнаружил, что, поскольку я использую Thin, мне не нужно запускать еще один EventMachine.
Мой блок after_initialize теперь выглядит так:
config.after_initialize do
include SomeModule
end
И в SomeModule я завернул свой код в EM.next_tick
блок или я получаю сообщение об ошибке "машина не инициализирована: evma_connect_to_server (RuntimeError)".
Использование EventMachine в Rails-приложении с Thin оказалось намного проще, чем я думал:)
Вы должны предотвратить автозагрузку вашего кода ruby, который вызывает EventMachine, иначе он заблокирует ваш основной поток. Поместите ваш скрипт в lib /daemons, затем создайте скрипт запуска для вашего EventMachine и используйте его в качестве демона. То есть:
#!/usr/bin/env ruby
# this is: ./scripts/my_daemon
require 'daemons'
options = {
multiple: false,
backtrace: true,
app_name: 'my_daemon',
dir_mode: :normal,
dir: '/tmp/my_daemon',
log_dir: '/tmp/my_daemon',
log_output: true,
ARGV: ARGV,
}
system "mkdir -p /tmp/my_daemons"
Daemons.run(File.join(File.dirname(__FILE__), '../lib/daemons/my_daemon.rb'), options)
Вам нужно будет добавить гем 'daemons' в ваш Gemfile.
Тогда просто беги script/my_daemon start
от корня рельсов. Есть еще команды:
- script/my_daemon stop # останавливает демон
- script/my_daemon run # выполняется на переднем плане, так что вы можете увидеть вывод и отладить его
- статус script/my_daemon # показывает, работает ли что-нибудь
Вы найдете журналы в /tmp/my_daemons/my_daemon.output
Узнайте больше о демонах здесь: http://daemons.rubyforge.org/Daemons.html