Это вторая часть серии, посвященной сравнению сред фоновой обработки Ruby. Вы можете проверить предыдущий пост, связанный выше. Подводя итоги первого поста, он охватывает принципы фоновой обработки (очереди, процессы и т. Д.). Кроме того, в статье рассматривается задержка_job (а также способы ее использования для создания фоновой работы и ее обработки), которая отлично подходит для быстрой фоновой обработки в вашем приложении. Тем не менее, он использует ActiveRecord, поэтому он довольно медленный, и вы в конечном итоге смешиваете фоновый и основной код во всем приложении.
Resque надеется решить обе эти проблемы, так что давайте окунемся!
Resque
Чтобы использовать Resque, вам нужно установить Redis. К счастью, у них есть отличная документация по установке . Если вы работаете в Mac OS X (как и многие из нас), все, что вам нужно сделать:
brew install redis
В Linux возможно установить Redis через менеджер пакетов. Например, в Debian / Ubuntu:
sudo apt-get install redis-server
Redis, к сожалению, не поддерживает Windows. Был представлен порт, но он не был объединен.
Установив Redis и запустив сервер Redis, вы можете добавить Resque в свой Gemfile:
gem 'resque'
А затем установите пакет:
bundle install
Вам нужно настроить грабли, которые позволят вам запустить рабочих с вашим Rails-приложением. Для этого добавьте файл в каталог «lib / tasks» с именем «resque.rake» (это определит задачи rake, связанные с Resque):
require 'resque/tasks'
Если вашим работникам нужен доступ к моделям (т. Е. Для фоновой обработки, которую вы будете выполнять, потребуется доступ к ActiveRecord и т. Д.), Вам необходимо добавить в этот файл следующее (lib / tasks / resque.rake):
task "resque:setup" => :environment
Наконец, вы должны создать отдельный каталог для ваших работников, так как они будут работать независимо от других аспектов вашего Rails-приложения. Я использую «приложение / работники» для этого.
Теперь, когда у нас есть начальная настройка, давайте напишем нашу первую работу с Resque. Сохраните следующее в app/workers/print_worker.rb
class PrintWorker @queue = :print def self.perform(str) puts "From print worker: " + str end end
Сам код очень прост, и работники обычно следуют этой схеме. Сначала вы определяете имя очереди как переменную экземпляра (вы можете назвать их как угодно). Затем все работники имеют метод класса с именем perform
. Это метод, который вызывается для обработки задания в очереди.
Например, если вы пишете работнику, которому нужно отправить какое-то электронное письмо, то именно здесь будет написан код, который отправляет электронное письмо.
В частности, PrintWorker
выполняет очень простую задачу; он берет строку, а затем печатает ее со специальной запиской «От печатника» перед ней.
Однако сейчас это не делает никакой работы; класс просто определен (т. е. в очереди нет заданий). Давайте это исправим.
Вот простой контроллер индекса (очевидно, вы можете взять материал внутри действия и поместить его в любой контроллер вашего приложения):
class IndexController < ApplicationController def index Resque.enqueue(PrintWorker, params[:to_print]) end end
Еще один очень простой фрагмент кода. Все, что он делает — это получает запрос пользователя на «index # index», а затем добавляет задание для работника печати. Но важный бит — это params[:to_print]
, который фактически указывает, что строка, которую PrintWorker
напечатает, определяется параметром GET
переданным действию index
.
Если мы перейдем к «/ index / index? To_print = somestring», PrintWorker
должен распечатать «somestring».
Однако где же это будет напечатано? Нам нужно настроить рабочий процесс! В отличие от delayed_job, Resque требует, чтобы вы настроили рабочий процесс, который «потребляет» очередь заданий. Давайте сделаем это прямо сейчас, набрав в терминале следующее:
rake resque:work QUEUE=print
Мы просто использовали одну из задач rake, предоставляемых resque, чтобы запустить рабочий процесс в очереди с именем print. Теперь это должно дать вам процесс, который, похоже, ничего не делает.
Укажите в вашем браузере «/ index / index? To_print = lol» (с правильным именем хоста, конечно) и проверьте вывод процесса, и вы должны увидеть, что печатник напечатал: «С печатника: lol».
Очевидно, это кажется очень простым примером, и это так. Но это действительно охватывает центральную идею resque; Работники определяются как классы с методом execute, очереди именуются, и вы можете передавать переменные работникам.
Хорошо, теперь, когда мы это знаем, давайте посмотрим на Resque по сравнению с delayed_job. Очевидно, с задержкой гораздо легче начать работу. Но, по моему мнению, код delayed_job имеет тенденцию извиваться довольно быстро, если вы не будете осторожны, потому что вы можете смешивать асинхронные вызовы с синхронными вызовами для одного и того же метода. Delayed_job также, вероятно, будет медленнее, так как он не использует хранилище в памяти по умолчанию.
Однако у delayed_job есть некоторые достоинства. Как уже упоминалось, это очень легко начать работать. Кроме того, его способности включают в себя некоторые вещи, которые Resque делает не очень хорошо, например, расстановка приоритетов.
Собственно говоря, Resque — это то, чем я пользуюсь ежедневно. Он сочетает в себе хороший способ структурировать ваш код, Redis и производительность в один прекрасный пакет.
Пример приложения
Чтобы продемонстрировать базовое использование Resque (а также быстро протестировать ваш экземпляр Redis), я создал небольшой пример приложения, которое позволяет вам запускать несколько простых рабочих на вашем компьютере. Он выполняет ту же функцию, что и пример приложения для delayed_job: асинхронно и синхронно выполняет подсчет страниц в файле. Это очень простое приложение, но оно служит рабочим примером для дальнейшего развития.
Проверьте это здесь
Будьте на связи!
В третьей части этой статьи будет рассказано о Sidekiq, а также общее сравнение трех фреймворков, которые обсуждались до сих пор (DelayedJob, Resque, Sidekiq).