Может войдёшь?
Черновики Написать статью Профиль

Очереди

перевод документация 4.x

  1. 1. Настройка
  2. 2. Основы использования
  3. 3. Добавление замыканий
  4. 4. Работа сервера приёма очереди
  5. 5. Демон-обработчик очереди
    1. 5.1. Развёртывание с помощью демонов-обработчиков очереди
    2. 5.2. Написание кода для демонов-обработчиков очереди
  6. 6. Push-очереди
  7. 7. Проваленные задачи
Этот перевод актуален для англоязычной документации на (ветка 4.2) , (ветка 4.1) и (ветка 4.0). Опечатка? Выдели и нажми Ctrl+Enter.

Настройка

В 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

Основы использования

Добавление новой задачи в очередь

PHP
Queue::push('SendEmail', array('message' => $message));

Регистрация обработчика задачи

Первый аргумент метода PHPQueue::push() — имя класса, который должен использоваться для обработки задачи. Второй аргумент — массив параметров, которые будут переданы обработчику. Обработчик задачи должен быть зарегистрирован так:

PHP
class SendEmail {

    public function 
fire($job$data) {
      
//
    
}

  }

Заметьте, что PHPfire() — единственный обязательный метод этого класса; он получает экземпляр объект PHPJob и массив данных, переданных при добавлении задачи в очередь.

Задача с произвольным методом-обработчиком

Если вы хотите использовать какой-то другой метод вместо fire — передайте его имя при добавлении задачи:

PHP
Queue::push('SendEmail@send', array('message' => $message));
+ 4.1

добавлено в 4.1 ()

Задание очереди для задачи

Вы можете задать очередь (queue или tube) в которую следует посылать задачу:

PHP
Queue::push('SendEmail@send', array('message' => $message), 'emails');

Передача одинаковых данных в несколько задач

Если вам надо передать одинаковые данные в несколько задач в очереди, вы можете использовать метод PHPQueue::bulk():

PHP
Queue::bulk(array('SendEmail''NotifyUser'), $payload);

Задержка выполнения задачи

Иногда вам может понадобиться задержать выполнение задачи в очереди. Например, вы захотите поместить в очередь задачу, которая отправляет пользователю e-mail через 15 минут после регистрации. Вы можете добиться этого, используя метод PHPQueue::later():

PHP
$date Carbon::now()->addMinutes(15);

Queue::later($date'SendEmail@send', array('message' => $message));

В этом примере мы используем библиотеку для работы со временем Carbon, чтобы указать необходимое время задержки для задачи. Другой вариант — передать необходимое число секунд для задержки.

Удаление выполненной задачи

Как только вы закончили обработку задачи она должна быть удалена из очереди — это можно сделать методом PHPdelete() объекта PHPJob:

PHP
public function fire($job$data) {
  
// Обработка задачи...

  
$job->delete();
}

Помещение задачи обратно в очередь

Если вы хотите поместить задачу обратно в очередь — используйте метод PHPrelease():

PHP
public function fire($job$data) {
  
// Обработка задачи...

  
$job->release();
}

Вы также можете указать число секунд, после которого задача будет помещена обратно:

PHP
$job->release(5);

Получение числа попыток запуска задания

Если во время обработки задания возникнет исключение, задание будет помещено обратно в очередь. Вы можете получить число сделанных попыток запуска задания методом PHPattempts():

PHP
if ($job->attempts() > 3) {
  
//
}

Получение идентификатора задачи

PHP
$job->getJobId();

Добавление замыканий

Вы можете помещать в очередь и функции-замыкания. Это очень удобно для простых, быстрых задач, выполняющихся в очереди.

Добавление замыкания в очередь

PHP
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

добавлено в 4.1 ()

Вы можете передать команде shlisten список подключений к очереди через запятую, чтобы задать приоритеты для очереди:

shphp artisan queue:listen --queue=high,low

В этом примере задачи из подключения high-connection всегда будут обрабатывать перед задачами из low-connection.

Указание времени на выполнение задачи

Кроме этого вы можете указать число секунд, в течение которых будет выполняться каждая задача:

shphp artisan queue:listen --timeout=60

Указание перерыва между задачами

Также вы можете задать число секунд ожидания перед проверкой наличия новых задач в очереди:

shphp artisan queue:listen --sleep=5

Обратите внимание, что очередь «засыпает» только тогда, когда в ней нет задач. Если задачи есть, очередь будет продолжать обрабатывать их без перерыва.

Обработка только первой задачи в очереди

Для обработки только первой задачи можно использовать команду queue:work:

shphp artisan queue:work
+ 4.2

добавлено в 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():

PHP
Route::post('queue/receive', function () {
  return 
Queue::marshal();
});

Этот метод позаботится о вызове нужного класса-обработчика задачи. Для помещения задач в push-очередь просто используйте всё тот же метод PHPQueue::push(), который работает и для обычных очередей.

+ 4.1

добавлено в 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.

PHP
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)

nikola166

Не совсем понятно различие между обычными очередями и Push-очередями.

Proger_XP

Обычные очереди требуют наличия процесса на сервере, который их будет запускать. Push-очереди — это, фактически, просто видимый из Сети скрипт, который периодически вызывается запросом с iron.io

nikola166

Что же лучше с точки зрения приозводительности?

Proger_XP

Внешние («push») очереди имеет смысл использовать только там, где нельзя настроить собственный процесс на сервере. Хотя, по идее, если у вас сервер упал, то iron.io дополнительно сообщит (так как не сможет вызывать скрипт с очередью), но это совсем необязательно будет так, лучше настроить нормальный отдельный монитор. Так что не вижу смысла использовать такие очереди в большей части проектов.

Лучше всего — собственные.

nikola166

спасибо за ответы

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.