Настройка
В Laravel, компонент Queue предоставляет единое API для различных сервисов очередей. Очереди позволяют вам отложить выполнение времязатратной задачи, такой как отправка e-mail, на более позднее время, таким образом на порядок ускоряя загрузку (генерацию) страницы.
Настройки очередей хранятся в файле app/config/queue.php. В нём вы найдёте настройки для драйверов-связей, которые поставляются вместе с фреймворком: Beanstalkd, IronMQ, Amazon SQS, Redis, а также синхронный драйвер (для локального использования).
Упомянутые выше драйвера имеют следующие зависимости:
- Beanstalkd: pda/pheanstalk ~2.0
- Amazon SQS: aws/aws-sdk-php
- IronMQ: iron-io/iron_mq
Основы использования
Добавление новой задачи в очередь
Queue::push('SendEmail', array('message' => $message));
Регистрация обработчика задачи
Первый аргумент метода PHPQueue::push()
— имя класса, который должен использоваться для обработки задачи. Второй аргумент — массив параметров, которые будут переданы обработчику. Обработчик задачи должен быть зарегистрирован так:
class SendEmail {
public function fire($job, $data) {
//
}
}
Заметьте, что PHPfire()
— единственный обязательный метод этого класса; он получает экземпляр объект PHPJob
и массив данных, переданных при добавлении задачи в очередь.
Задача с произвольным методом-обработчиком
Если вы хотите использовать какой-то другой метод вместо fire — передайте его имя при добавлении задачи:
Queue::push('SendEmail@send', array('message' => $message));
добавлено в 4.1 ()
Вы можете задать очередь (queue или tube) в которую следует посылать задачу:
Queue::push('SendEmail@send', array('message' => $message), 'emails');
Передача одинаковых данных в несколько задач
Если вам надо передать одинаковые данные в несколько задач в очереди, вы можете использовать метод PHPQueue::bulk()
:
Queue::bulk(array('SendEmail', 'NotifyUser'), $payload);
Иногда вам может понадобиться задержать выполнение задачи в очереди. Например, вы захотите поместить в очередь задачу, которая отправляет пользователю e-mail через 15 минут после регистрации. Вы можете добиться этого, используя метод PHPQueue::later()
:
$date = Carbon::now()->addMinutes(15);
Queue::later($date, 'SendEmail@send', array('message' => $message));
В этом примере мы используем библиотеку для работы со временем Carbon, чтобы указать необходимое время задержки для задачи. Другой вариант — передать необходимое число секунд для задержки.
Как только вы закончили обработку задачи она должна быть удалена из очереди — это можно сделать методом PHPdelete()
объекта PHPJob
:
public function fire($job, $data) {
// Обработка задачи...
$job->delete();
}
Помещение задачи обратно в очередь
Если вы хотите поместить задачу обратно в очередь — используйте метод PHPrelease()
:
public function fire($job, $data) {
// Обработка задачи...
$job->release();
}
Вы также можете указать число секунд, после которого задача будет помещена обратно:
$job->release(5);
Получение числа попыток запуска задания
Если во время обработки задания возникнет исключение, задание будет помещено обратно в очередь. Вы можете получить число сделанных попыток запуска задания методом PHPattempts()
:
if ($job->attempts() > 3) {
//
}
Получение идентификатора задачи
$job->getJobId();
Добавление замыканий
Вы можете помещать в очередь и функции-замыкания. Это очень удобно для простых, быстрых задач, выполняющихся в очереди.
Добавление замыкания в очередь
Queue::push(function ($job) use ($id) {
Account::delete($id);
$job->delete();
});
Вместо того, чтобы делать объекты доступными для замыканий очередей через директиву PHPuse
, передавайте первичные ключи и повторно извлекайте связанные модели из вашей задачи в очереди. Это часто позволяет избежать неожиданного поведения при сериализации.
Константы PHP__DIR__
и PHP__FILE__
не должны использоваться в замыканиях.
При использовании push-очередей Iron.io будьте особенно внимательны при добавлении замыканий. Конечная точка выполнения, получающая ваше сообщение, должна проверить входящую последовательность-ключ, чтобы удостовериться, что запрос действительно исходит от Iron.io. Например, ваша конечная push-точка может иметь адрес вида https://yourapp.com/queue/receive?token=SecretToken — где значение token можно проверять перед собственно обработкой задачи.
Работа сервера приёма очереди
Laravel включает в себя задание Artisan, которое будет выполнять новые задачи по мере их поступления. Вы можете запустить его командой queue:listen.
shphp artisan queue:listen
Вы также можете указать, какое именно соединение должно прослушиваться:
shphp artisan queue:listen connection
Заметьте, что когда это задание запущено оно будет продолжать работать, пока вы не остановите его вручную. Вы можете использовать монитор процессов, такой как Supervisor, чтобы удостовериться, что задание продолжает работать.
добавлено в 4.1 ()
Указание времени на выполнение задачи
Кроме этого вы можете указать число секунд, в течение которых будет выполняться каждая задача:
shphp artisan queue:listen --timeout=60
Указание перерыва между задачами
Также вы можете задать число секунд ожидания перед проверкой наличия новых задач в очереди:
shphp artisan queue:listen --sleep=5
Обратите внимание, что очередь «засыпает» только тогда, когда в ней нет задач. Если задачи есть, очередь будет продолжать обрабатывать их без перерыва.
Обработка только первой задачи в очереди
Для обработки только первой задачи можно использовать команду queue:work:
shphp artisan queue:work
добавлено в 4.2 ()
Демон-обработчик очереди
Команда shqueue:work
также имеет опцию sh--daemon
для того, чтобы обработчик принудительно продолжал обрабатывать задачи без необходимости повторной загрузки фреймворка. Это приводит к значительному снижению использования CPU по сравнению с командой shqueue:listen
, но добавляет сложности из-за необходимости в избавлении от очередей текущих задач во время вашего развёртывания.
Для запуска обработчика очереди в режиме демона используйте флаг sh--daemon
:
shphp artisan queue:work connection --daemon php artisan queue:work connection --daemon --sleep=3 php artisan queue:work connection --daemon --sleep=3 --tries=3
Как видите, команда shqueue:work
поддерживает те же самые опции, что и команда shqueue:listen
. Для просмотра всех доступных опций используйте команду shphp artisan help queue:work
.
Развёртывание с помощью демонов-обработчиков очереди
Простейший способ развернуть приложение, используя обработчики очереди, — перевести приложение в режим техобслуживания в начале развёртывания. Это можно сделать с помощью команды shphp artisan down
. Когда приложение перейдет в режим обслуживания, Laravel не будет принимать новые задачи из очереди, но продолжит обработку имеющихся задач.
Самый лёгкий способ перезапуска ваших обработчиков — включить следующую команду в ваш скрипт для развёртывания:
shphp artisan queue:restart
Эта команда сообщит всем обработчикам очереди о необходимости перезапуска после завершения обработки их текущих задач.
Эта команда полагается на систему кэша для планирования перезапуска. По умолчанию APCu не работает для терминальных команд. Если вы используете APCu, добавьте confapc.enable_cli=1
в свою конфигурацию для APCu.
Написание кода для демонов-обработчиков очереди
Демоны-обработчики очереди не перезапускают фреймворк перед обработкой каждой задачи. Поэтому нужно быть аккуратным при освобождении любых «тяжёлых» ресурсов до того, как закончится выполнение вашей задачи. Например, если вы обрабатываете изображение с помощью библиотеки GD, то после завершения обработки вам необходимо освобождать память с помощью PHPimagedestroy
.
Так же, ваше соединение с БД может быть потеряно, когда оно используется демоном долгое время. Вы можете использовать метод PHPDB::reconnect()
, для обеспечения «свежего» соединения.
Push-очереди
Push-очереди дают вам доступ ко всем мощным возможностям, предоставляемым подсистемой очередей Laravel 4 без запуска серверов или фоновых программ. На текущий момент push-очереди поддерживает только драйвер Iron.io. Перед тем, как начать, создайте аккаунт и впишите его данные в app/config/queue.php.
Регистрация подписчика push-очереди
После этого вы можете использовать Artisan-команду queue:subscribe для регистрации URL конечной точки, которая будет получать добавляемые в очередь задачи:
shphp artisan queue:subscribe queue_name http://foo.com/queue/receive
Теперь, когда вы войдёте в ваш профиль Iron.io, то увидите новую push-очередь и её URL подписки. Вы можете подписать любое число URL на одну очередь. Дальше создайте маршрут для вашей конечной точки queue/receive и пусть он возвращает результат вызова метода PHPQueue::marshal()
:
Route::post('queue/receive', function () {
return Queue::marshal();
});
Этот метод позаботится о вызове нужного класса-обработчика задачи. Для помещения задач в push-очередь просто используйте всё тот же метод PHPQueue::push()
, который работает и для обычных очередей.
добавлено в 4.1 ()
Проваленные задачи
Не всегда всё идёт по плану, иногда ваши задачи в очереди будут заканчиваться ошибкой. Не волнуйтесь, такое с каждым случается! В Laravel есть удобный способ указать максимальное количество попыток выполнения задачи. После превышения этого количества попыток, задача будет добавлена в таблицу failed_jobs. Название таблицы проваленных задач может быть настроено в файле app/config/queue.php.
Для создания миграции для таблицы failed_jobs, можно использовать команду shqueue:failed-table
:
shphp artisan queue:failed-table
Указать максимальное количества попыток выполнения задачи можно с помощью ключа sh--tries
команды shqueue:listen
:
shphp artisan queue:listen connection-name --tries=3
Если вы хотите зарегистрировать событие, которое будет вызываться при ошибке выполнения задачи, можете использовать метод PHPQueue::failing()
. Это событие — отличная возможность оповестить вашу команду через e-mail или HipChat.
Queue::failing(function($connection, $job, $data)
{
//
});
Чтобы просмотреть все проваленные задачи, можно использовать Artisan-команду shqueue:failed
:
shphp artisan queue:failed
Эта команда выведет список задач с их ID, подключением, очередью и временем ошибки. ID задачи можно использовать для повторной попытки её выполнения. Например, для повторной попытки выполнения задачи с ID = 5 надо выполнить такую команду:
shphp artisan queue:retry 5
Если вы хотите удалить проваленную задачу, используйте команду shqueue:forget
:
shphp artisan queue:forget 5
Для удаления всех проваленных задач используйте команду shqueue:flush
:
shphp artisan queue:flush
Комментарии (5)
Не совсем понятно различие между обычными очередями и Push-очередями.
Обычные очереди требуют наличия процесса на сервере, который их будет запускать. Push-очереди — это, фактически, просто видимый из Сети скрипт, который периодически вызывается запросом с iron.io
Что же лучше с точки зрения приозводительности?
Внешние («push») очереди имеет смысл использовать только там, где нельзя настроить собственный процесс на сервере. Хотя, по идее, если у вас сервер упал, то iron.io дополнительно сообщит (так как не сможет вызывать скрипт с очередью), но это совсем необязательно будет так, лучше настроить нормальный отдельный монитор. Так что не вижу смысла использовать такие очереди в большей части проектов.
Лучше всего — собственные.
спасибо за ответы