EventMachine и Ruby Threads - что здесь происходит на самом деле? - PullRequest
6 голосов
/ 05 ноября 2011

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

if defined?(PhusionPassenger)
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
  # for passenger, we need to avoid orphaned threads
    if forked && EM.reactor_running?
      EM.stop
    end
    Thread.new {
      EM.run do

Мой вопрос связан с EM.reactor_running? и команды EM.stop. Если Пассажир разорвал наш процесс, зачем мне перезапускать ссылку EM в новом потоке? Если EM.reactor_running? возвращает true, на какой экземпляр EM я ссылаюсь?

Вы можете увидеть полный код инициализатора в нашем блоге здесь http://www.hiringthing.com/2011/11/04/eventmachine-with-rails.html

1 Ответ

13 голосов
/ 07 ноября 2011

Прежде всего, существует только один экземпляр EventMachine для каждого процесса Ruby, поэтому независимо от того, что вы всегда будете ссылаться на один и тот же экземпляр EM, независимо от потока, в котором вы сейчас находитесь.

Вы запускаете реактор в новом отдельном потоке, чтобы он не блокировал основной поток (целью которого является обслуживание веб-запроса). В противном случае EM.run взял бы управление на себя, войдя в цикл выполнения и больше не выходя из блока EM.run. EM.reactor_running? возвращает true, хорошо, если где-то работает цикл EM. Поскольку для каждого процесса в Ruby существует только один метод, достаточно просто определить, работает EM или нет.

У вас есть простейший способ использовать EM внутри обычного процесса Ruby, не мешая всему, что работает. Я предполагаю, что вы отправляете сообщения брокеру AMQP из своего веб-приложения. Всякий раз, когда вы отправляете сообщение, оно входит в цикл выполнения EM в отдельном потоке, эта часть довольно прозрачна для вас и не влияет на основной цикл, который может продолжить обработку веб-запроса Rails. Будьте осторожны, чтобы всегда вставлять вещи в цикл EM, используя EM.next_tick. Попытка обработать сокеты, открытые EM в разных потоках, может привести к тому, что произойдут плохие вещи, что я наблюдал в производственной среде, между прочим, используя и создавая библиотеку, называемую случившимся;)

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

...