Какой лучший способ организовать рабочие процессы в Rails?
У меня часто есть код, который должен запускаться либо по расписанию, либо как фоновый процесс с некоторыми параметрами. Общий элемент заключается в том, что они запускаются за пределами процесса отправки, но им нужен доступ к среде Rails (и, возможно, к параметрам, переданным в).
Какой хороший способ организовать это и почему? Если вам нравится использовать какой-либо конкретный плагин или драгоценный камень, объясните, почему вы считаете его удобным - не просто перечислите плагин, который вы используете.
Ответы
Ответ 1
Для меня не нужно поддерживать большую часть дополнительной инфраструктуры, поэтому я использовал очереди с поддержкой базы данных, которые выполняются за пределами Rails.
В моем случае я использовал background_job
и delayed_job. С background_job
рабочий продолжал работать через cron, поэтому никакого управления демоном не было. С delayed_job
, я использую Heroku и позволяю им беспокоиться об этом.
С delayed_job вы можете передать столько аргументов, сколько нужно выполнить фоновому работнику.
Delayed::Job.enqueue(MyJob.new(param[:one], param[:two], param[:three])
Я не нашел хорошего решения для запуска материала по расписанию, кроме использования script/runner
через cron (я предпочитаю использовать script/runner
для задачи Rake, потому что мне легче протестировать код).
Мне никогда не приходилось регулярно планировать фоновый процесс, требующий доступа к определенному запросу Rails, так что это не было проблемой.
Я знаю, что есть и другие, более холодные системы с большим количеством функций, но это сработало нормально для меня и помогает мне не справляться с настройкой множества новых сервисов для управления.
Ответ 2
Мне действительно не нравятся такие драгоценные камни, как delayed_job
и background_job
, которые сохраняются в базе данных с целью запуска асинхронных заданий. Мне это кажется грязным. Переходные материалы не входят в базу данных.
Я большой поклонник очередей сообщений для работы с асинхронными задачами, даже если у вас нет необходимости в массивной масштабируемости. То, как я это вижу, очереди сообщений - идеальный "lingua franca" для сложных систем. В очереди сообщений в большинстве случаев у вас нет ограничений на технологии или языки, которые участвуют в том, что вы строите. Преимущества использования очереди сообщений низкого уровня concurrency, вероятно, наиболее заметны в среде "enterpriseisey", где интеграция всегда является огромной болью. Кроме того, очереди сообщений идеальны, когда ваш асинхронный рабочий процесс включает в себя несколько шагов. RabbitMQ - мой личный фаворит.
Например, рассмотрим сценарий, в котором вы строите поисковую систему. Люди могут отправлять индексы URI. Очевидно, что вы не хотите извлекать и индексировать страницу в запросе. Таким образом, вы создаете вокруг очереди сообщений: цель представления формы принимает URI, выдает ее в очередь сообщений для индексирования. Следующий доступный процесс паука выталкивает URI из очереди, извлекает страницу, находит все ссылки, выталкивает каждый из них обратно в очередь, если они неизвестны, и кэширует содержимое. Наконец, новое сообщение помещается во вторую очередь для процесса индексатора для работы с кэшированным контентом. Процесс индексатора выводит это сообщение из очереди и индексирует кешированный контент. Разумеется, упрощение - поисковые системы - это большая работа, но вы получаете идею.
Что касается реальных демонов, очевидно, я частично отношусь к своей собственной библиотеке (ChainGang), но это действительно просто обертка вокруг Kernel.fork(), которая дает вам удобное место для работы с кодом настройки и разрыва. Это еще не совсем сделано. Часть демона намного менее важна, чем очередь сообщений.
Что касается среды Rails, то, вероятно, это лучше всего оставить в качестве упражнения для читателя, поскольку использование памяти будет значительным фактором, что при длительном процессе. Вы не хотите загружать все, что вам не нужно. Кстати, это одна из областей, в которой DataMapper отлично работает с ActiveRecord. Инициализация среды хорошо документирована, и в ней задействовано гораздо меньше зависимостей, что делает весь комплект и caboodle значительно более реалистичными.
Единственное, что мне не нравится в cron + rake, - это то, что грабли практически гарантированно печатаются на стандартный вывод, а cron имеет тенденцию быть чрезмерно болтливым, если ваши задания cron производят выход. Мне нравится ставить все мои задачи cron в директорию с соответствующим именем, а затем делать задачу рейка, которая их обертывает, так что тривиально запускать их вручную. Это позор, что рейк делает это, потому что я действительно предпочел бы иметь возможность использовать зависимости. В любом случае вы просто указываете cron непосредственно на сценарии, а не на их запуск через cron.
В настоящее время я занимаюсь разработкой веб-приложения, которое в значительной степени опирается на асинхронные процессы, и я должен сказать, что я очень, очень рад, что решил не использовать Rails.
Ответ 3
У меня есть система, которая получает запросы, а затем требует вызова нескольких внешних систем с использованием веб-сервисов. Некоторые из этих запросов занимают больше времени, чем можно ожидать ожидания пользователя, и я использую систему очередей предприятий (activemq) для обработки этих запросов.
Я использую плагин ActiveMessaging. Это позволяет мне сортировать запрос и помещать его в очередь для асинхронной обработки с доступом к данным запроса, однако вам нужно будет написать услугу опроса, если вы хотите дождаться ответа.
Я видел Ryan Bates railscast на Starling и Workling, и они выглядят многообещающими, но я не использовал их.
Ответ 4
Для регулярных заданий я просто использую задачи rake. Он прост, легко тестируется, легко понимается и хорошо интегрируется с средой Rails. Затем просто выполняйте эти задачи rake с заданием cron в любой промежуток времени, который вам нужен (я использую whenever для управления этими заданиями, потому что я немного крон-неграмотны).