Лучшая практика Rails: фоновый процесс / поток? - PullRequest
2 голосов
/ 08 мая 2011

Я пришел из среды PHP (по крайней мере, с точки зрения веб-разработчика) в прекрасный мир Ruby, поэтому у меня могут возникнуть некоторые глупые вопросы.Я предполагаю, что есть некоторые принципиально разные опции, доступные, когда не используется PHP.

В PHP мы используем memcache для хранения предупреждений, которые мы хотим отобразить в строке вверху страницы.Когда происходит что-то, генерирующее оповещение (например, о создании новой записи в блоге), скрипт cron, который запускается каждые 5 минут или около того, помещает эту информацию в memcache.

Теперь, когда пользователь посещает сайт, мызагляните в memcache, чтобы найти любые оповещения, которые они еще не отклонили, и мы их отображаем.

То, что я могу сделать по-другому в Rails, это обойти необходимость скрипта cron, итакже необходимо искать в memcache каждый запрос, используя Singleton и процесс опроса, выполняющийся в отдельном потоке для копирования из memcache в этот singleton.Теоретически это было бы более оптимизированным, чем проверка memcache один раз на запрос, а также инкапсулировать логику опроса в одном месте, а не разделять ее между задачей cron и логикой поиска.

Мой вопрос:Есть ли какие-то предостережения относительно наличия некоторого runloop в фоновом режиме, пока запущено приложение Rails?Я понимаю последствия многопоточности из Objective-C / Java, но я спрашиваю конкретно о среде Rails (3).

В основном что-то вроде:

class SiteAlertsMap < Hash
  include Singleton

  def initialize
    super
    begin_polling
  end

  # ... SNIP, any specific methods etc ...

  private

    def begin_polling
      # Create some other Thread here, which polls at set intervals
    end
end

Это подводит меняв похожий вопрос.Мы помещаем (зашифрованные) задачи в очередь SQS для вещей, связанных с электронной торговлей и для длительных фоновых задач.Для этого мы не используем cron, но у нас есть рабочий демон, написанный на PHP, который работает в фоновом режиме.Прямо сейчас, когда мы внедряем, мы должны выключить этого работника и запустить его заново с новой базы кода.В Rails можно ли как-нибудь запустить и остановить этот процесс на самом сервере rails (единорог)?Я не думаю, что это то, что я запускаю в главном процессе в отдельном потоке, так как мы часто хотим контролировать его как процесс сам по себе, но было бы неплохо, если бы он просто удобно запускался во время работы веб-приложения.

1 Ответ

7 голосов
/ 09 мая 2011

Потоки для фоновых процессов в ruby ​​были бы ужасной ошибкой, особенно если вы используете многопроцессорный сервер.Использование единорога, скажем, с 4 рабочими процессами будет означать, что вы будете опрашивать каждый из них, а это не то, что вам нужно.В Ruby на самом деле нет реальных потоков, у него зеленые потоки в 1.8 и глобальная блокировка интерпретатора в 1.9 IIRC.Многие гемы и библиотеки также неприятно небезопасны.

Использование memcache по-прежнему является вашим лучшим вариантом, и, если вы настроили его правильно, вы должны увидеть, как он добавляет миллисекунду или две ко времени запроса.Другим вариантом, который даст вам преимущество сохранения этих предупреждений при минимальных дополнительных затратах, будет сохранение этих предупреждений в Redis.Это лучше защитит вас от таких вещей, как сбой memcache или перезагрузка сервера.

Для фоновых заданий вы должны использовать подход, аналогичный тому, который используется сейчас, но есть несколько готовых обработчиков для этого, например resque , delayed_job и некоторые другие.Если вам абсолютно необходимо использовать SQS в качестве внутренней очереди, вы можете найти какой-то код, который вам поможет, но в противном случае вы могли бы написать его самостоятельно.Это по-прежнему требует перезагрузки другого демона при каждом изменении кода.На практике это не является большой проблемой, так как лучшие практики диктуют использование системы развертывания, такой как capistrano, где можно легко добавить правило для отказов демона при развертывании.Я использую monit для наблюдения за процессом демона, поэтому перезапустить его так же просто, как сказать monit, чтобы перезапустить его.

В общем, Ruby не похож на Java / Objective-C, когда речь идет о потоках.Он следует более Unix-подобной модели изоляции на основе процессов, но сообщество разработало лучшие практики и способы сделать это менее болезненным, чем в других языках.Ruby требует немного большего внимания к настройке своего стека, поскольку это не так просто, как включение mod_php и копирование некоторых файлов, но как только вы поймете выбор и архитектуру, вам будет легче понять, как работает ваше приложение.Модель процесса, на мой взгляд, намного лучше для веб-приложений, поскольку она изолирует код и состояние от влияния других выполняющихся операций.Изоляция также облегчает работу приложения в распределенной системе.

...