Вступление
Laravel теперь предлагает Horizon, красивую панель инструментов и систему конфигурации для ваших очередей с питанием от Redis. Ознакомьтесь с полной документацией Horizon для получения дополнительной информации.
Очереди Laravel предоставляют унифицированный API для различных серверных частей, таких как Beanstalk, Amazon SQS, Redis или даже реляционная база данных. Очереди позволяют отложить обработку трудоемкой задачи, такой как отправка электронной почты, до более позднего времени. Откладывание этих трудоемких задач значительно ускоряет веб-запросы к вашему приложению.
Файл конфигурации очереди хранится в . В этом файле вы найдете конфигурации подключения для каждого из драйверов очереди, которые включены в платформу, которая включает в себя базу данных, Beanstalkd , Amazon SQS , Redis и синхронный драйвер, который будет выполнять задания немедленно (для локального использования). Водитель очереди также включен , который удаляет из очереди заданий.config/queue.php
null
Соединения Vs. Очереди
Прежде чем начать работу с очередями Laravel, важно понять различие между «соединениями» и «очередями». В вашем файле конфигурации есть опция конфигурации. Этот параметр определяет конкретное соединение с серверной службой, такой как Amazon SQS, Beanstalk или Redis. Однако любое заданное соединение с очередью может иметь несколько «очередей», которые могут рассматриваться как разные стеки или группы заданий в очереди.config/queue.php
connections
Обратите внимание, что каждый пример конфигурации соединения в queue
файле конфигурации содержит queue
атрибут. Это очередь по умолчанию, в которую будут отправляться задания при отправке в данное соединение. Другими словами, если вы отправляете задание без явного определения, в какую очередь оно должно быть отправлено, задание будет помещено в очередь, определенную в queue
атрибуте конфигурации соединения:
// This job is sent to the default queue...
Job::dispatch();
// This job is sent to the "emails" queue...
Job::dispatch()->onQueue('emails');
Некоторым приложениям может не потребоваться помещать задания в несколько очередей, вместо этого они предпочитают иметь одну простую очередь. Однако отправка заданий в несколько очередей может быть особенно полезна для приложений, которые хотят расставить приоритеты или сегментировать процесс обработки заданий, поскольку работник очереди Laravel позволяет указать, какие очереди следует обрабатывать по приоритету. Например, если вы помещаете задания в high
очередь, вы можете запустить работника, который дает им более высокий приоритет обработки:
php artisan queue:work --queue=high,default
Примечания и предпосылки для водителя
База данных
Чтобы использовать database
драйвер очереди, вам понадобится таблица базы данных для хранения заданий. Чтобы сгенерировать миграцию, создающую эту таблицу, выполните команду Artisan. После того, как миграция была создана, вы можете перенести вашу базу данных с помощью команды:queue:table
migrate
php artisan queue:table
php artisan migrate
Redis
Чтобы использовать redis
драйвер очереди, вы должны настроить соединение с базой данных Redis в вашем файле конфигурации.config/database.php
Redis Cluster
Если ваше подключение к очереди Redis использует кластер Redis, имена очереди должны содержать ключевой хэш-тег . Это необходимо для того, чтобы все ключи Redis для данной очереди были помещены в один и тот же хэш-слот:
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => '{default}',
'retry_after' => 90,
],
блокировка
При использовании очереди Redis вы можете использовать block_for
опцию конфигурации, чтобы указать, как долго драйвер должен ждать, пока задание станет доступным, прежде чем выполнять итерацию рабочего цикла и повторный опрос базы данных Redis.
Регулировка этого значения в зависимости от загрузки очереди может быть более эффективной, чем постоянный опрос базы данных Redis на наличие новых заданий. Например, вы можете установить значение, чтобы 5
указать, что драйвер должен блокироваться в течение пяти секунд, ожидая, пока задание станет доступным:
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
'retry_after' => 90,
'block_for' => 5,
],
Другие условия для водителя
Для перечисленных драйверов очереди необходимы следующие зависимости:
- Amazon SQS:
aws/aws-sdk-php ~3.0
- Beanstalkd:
pda/pheanstalk ~4.0
- Redis:
predis/predis ~1.0
Создание рабочих мест
Генерация рабочих классов
По умолчанию все очереди задач для вашего приложения хранятся в каталоге. Если каталог не существует, он будет создан при запуске команды Artisan. Вы можете создать новое задание в очереди с помощью Artisan CLI:app/Jobs
app/Jobs
make:job
php artisan make:job ProcessPodcast
Сгенерированный класс будет реализовывать интерфейс, указывающий Laravel, что задание должно быть помещено в очередь для асинхронного запуска.Illuminate\Contracts\Queue\ShouldQueue
Структура класса
Классы заданий очень просты, обычно содержат только handle
метод, который вызывается, когда задание обрабатывается в очереди. Для начала давайте рассмотрим пример класса работы. В этом примере мы представим, что управляем службой публикации подкастов и должны обработать загруженные файлы подкастов перед их публикацией:
<?php
namespace App\Jobs;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* Create a new job instance.
*
* @param Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* Execute the job.
*
* @param AudioProcessor $processor
* @return void
*/
public function handle(AudioProcessor $processor)
{
// Process uploaded podcast...
}
}
В этом примере обратите внимание, что мы смогли передать модель Eloquent непосредственно в конструктор заданий в очереди. Из-за SerializesModels
особенностей, которые использует задание, модели Eloquent будут изящно сериализованы и не сериализованы при обработке задания. Если ваше задание в очереди принимает модель Eloquent в своем конструкторе, только идентификатор модели будет сериализован в очередь. Когда задание действительно обработано, система очередей автоматически повторно извлечет полный экземпляр модели из базы данных. Все это полностью прозрачно для вашего приложения и предотвращает проблемы, которые могут возникнуть при сериализации полных экземпляров модели Eloquent.
handle
Метод вызывается , когда задание обрабатывается очереди. Обратите внимание, что мы можем указать зависимости подсказки от handle
метода задания. Сервисный контейнер Laravel автоматически внедряет эти зависимости.
Если вы хотите получить полный контроль над тем, как контейнер внедряет зависимости в handle
метод, вы можете использовать метод контейнера bindMethod
. bindMethod
Метод принимает функцию обратного вызова , который принимает работу и контейнер. Внутри обратного вызова вы можете вызывать handle
метод по своему усмотрению. Как правило, вы должны вызывать этот метод у поставщика услуг :
use App\Jobs\ProcessPodcast;
$this->app->bindMethod(ProcessPodcast::class.'@handle', function ($job, $app) {
return $job->handle($app->make(AudioProcessor::class));
});
Двоичные данные, такие как необработанное содержимое изображения, должны быть переданы через
base64_encode
функцию перед передачей в очередь. В противном случае задание может неправильно сериализоваться в JSON при помещении в очередь.
Диспетчерские вакансии
После того, как вы написали свой класс работы, вы можете отправить его, используя dispatch
метод самой работы. Аргументы, переданные dispatch
методу, будут переданы конструктору задания:
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessPodcast;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PodcastController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Create podcast...
ProcessPodcast::dispatch($podcast);
}
}
Задержка отправки
Если вы хотите отложить выполнение задания из очереди, вы можете использовать этот delay
метод при отправке задания. Например, давайте укажем, что задание не должно быть доступно для обработки до 10 минут после отправки:
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessPodcast;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PodcastController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Create podcast...
ProcessPodcast::dispatch($podcast)
->delay(now()->addMinutes(10));
}
}
Служба очереди Amazon SQS имеет максимальное время задержки 15 минут.
Синхронная диспетчеризация
Если вы хотите отправить задание немедленно (синхронно), вы можете использовать этот dispatchNow
метод. При использовании этого метода задание не будет поставлено в очередь и будет немедленно запущено в текущем процессе:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Jobs\ProcessPodcast;
use App\Http\Controllers\Controller;
class PodcastController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Create podcast...
ProcessPodcast::dispatchNow($podcast);
}
}
Цепочка вакансий
Цепочка заданий позволяет вам указать список заданий в очереди, которые должны выполняться последовательно. В случае сбоя одного задания в последовательности остальные задания не будут выполнены. Чтобы выполнить цепочку заданий, поставленных в очередь, вы можете использовать withChain
метод для любого из ваших диспетчеризуемых заданий:
ProcessPodcast::withChain([
new OptimizePodcast,
new ReleasePodcast
])->dispatch();
Удаление заданий с использованием этого метода не помешает выполнению связанных заданий. Цепочка прекратит выполнение только в случае сбоя задания в цепочке.
$this->delete()
Цепное соединение и очередь
Если вы хотите , чтобы указать соединение по умолчанию и очередь , которая должна быть использована для прикованных заданий, вы можете использовать allOnConnection
и allOnQueue
методу. Эти методы указывают соединение с очередью и имя очереди, которые следует использовать, если заданию в очереди явно не назначено другое соединение / очередь:
ProcessPodcast::withChain([
new OptimizePodcast,
new ReleasePodcast
])->dispatch()->allOnConnection('redis')->allOnQueue('podcasts');
Настройка очереди и соединения
Отправка в определенную очередь
Перемещая задания в разные очереди, вы можете «классифицировать» задания, поставленные в очередь, и даже расставить приоритеты по количеству работников, назначенных для разных очередей. Имейте в виду, что это не подталкивает задания к различным «соединениям» очереди, как определено вашим файлом конфигурации очереди, а только к определенным очередям в пределах одного соединения. Чтобы указать очередь, используйте onQueue
метод при отправке задания:
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessPodcast;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PodcastController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Create podcast...
ProcessPodcast::dispatch($podcast)->onQueue('processing');
}
}
Отправление к определенному соединению
Если вы работаете с несколькими подключениями к очереди, вы можете указать, к какому соединению следует добавить задание. Чтобы указать соединение, используйте onConnection
метод при отправке задания:
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessPodcast;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PodcastController extends Controller
{
/**
* Store a new podcast.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Create podcast...
ProcessPodcast::dispatch($podcast)->onConnection('sqs');
}
}
Вы можете приковать onConnection
и onQueue
методы для определения соединения и очереди на работу:
ProcessPodcast::dispatch($podcast)
->onConnection('sqs')
->onQueue('processing');
В качестве альтернативы вы можете указать connection
как свойство в классе задания:
<?php
namespace App\Jobs;
class ProcessPodcast implements ShouldQueue
{
/**
* The queue connection that should handle the job.
*
* @var string
*/
public $connection = 'sqs';
}
Задание максимальных попыток задания / значений тайм-аута
Макс Попытки
Один из подходов к определению максимального количества попыток выполнения задания - через --tries
переключатель в командной строке Artisan:
php artisan queue:work --tries=3
Однако вы можете выбрать более детальный подход, определив максимальное количество попыток для самого класса заданий. Если в задании указано максимальное количество попыток, оно будет иметь приоритет над значением, указанным в командной строке:
<?php
namespace App\Jobs;
class ProcessPodcast implements ShouldQueue
{
/**
* The number of times the job may be attempted.
*
* @var int
*/
public $tries = 5;
}
Попытки, основанные на времени
В качестве альтернативы определению того, сколько раз может быть выполнено задание до его сбоя, вы можете указать время, в течение которого задание должно прерваться. Это позволяет выполнить задание любое количество раз в течение определенного периода времени. Чтобы определить время, в которое задание должно истечь, добавьте retryUntil
метод в свой класс задания:
/**
* Determine the time at which the job should timeout.
*
* @return \DateTime
*/
public function retryUntil()
{
return now()->addSeconds(5);
}
Вы также можете определить
retryUntil
метод для своих слушателей событий в очереди.
Тайм-аут
timeout
Функция оптимизирована для PHP 7.1+ иpcntl
расширение PHP.
Аналогично, максимальное количество секунд, которое могут выполняться задания, может быть указано с помощью --timeout
переключателя в командной строке Artisan:
php artisan queue:work --timeout=30
Однако вы также можете определить максимальное количество секунд, которое должно быть разрешено заданию для самого класса задания. Если для задания указано время ожидания, оно будет иметь приоритет над любым временем ожидания, указанным в командной строке:
<?php
namespace App\Jobs;
class ProcessPodcast implements ShouldQueue
{
/**
* The number of seconds the job can run before timing out.
*
* @var int
*/
public $timeout = 120;
}
Ограничение скорости
Эта функция требует, чтобы ваше приложение могло взаимодействовать с сервером Redis .
Если ваше приложение взаимодействует с Redis, вы можете ограничить количество заданий в очереди по времени или параллелизму. Эта функция может быть полезна, когда ваши задания в очереди взаимодействуют с API, которые также ограничены по скорости.
Например, используя throttle
метод, вы можете ограничить задание определенного типа, чтобы оно выполнялось только 10 раз каждые 60 секунд. Если блокировка не может быть получена, вы обычно должны вернуть задание обратно в очередь, чтобы его можно было повторить позже:
Redis::throttle('key')->allow(10)->every(60)->then(function () {
// Job logic...
}, function () {
// Could not obtain lock...
return $this->release(10);
});
В приведенном выше примере,
Выпуск задушенного задания обратно в очередь по-прежнему увеличивает общее число заданийkey
может быть любая строка, которая однозначно определяет тип задания, которое вы хотели бы ограничить. Например, вы можете создать ключ на основе имени класса задания и идентификаторов моделей Eloquent, с которыми оно работает.attempts
.
Кроме того, вы можете указать максимальное количество работников, которые могут одновременно обрабатывать задание. Это может быть полезно, когда задание в очереди изменяет ресурс, который должен изменяться только одним заданием за раз. Например, используя funnel
метод, вы можете ограничить выполнение заданий определенного типа только одним рабочим за раз:
Redis::funnel('key')->limit(1)->then(function () {
// Job logic...
}, function () {
// Could not obtain lock...
return $this->release(10);
});
При использовании ограничения скорости может быть трудно определить количество попыток, необходимых для успешного выполнения вашей работы. Поэтому полезно сочетать ограничение скорости с попытками, основанными на времени .
Обработка ошибок
Если во время обработки задания возникает исключение, задание будет автоматически возвращено в очередь, поэтому его можно повторить. Задание будет продолжать освобождаться до тех пор, пока не будет предпринято максимальное количество попыток, допустимое вашим приложением. Максимальное количество попыток определяется --tries
переключателем, используемым в команде Artisan. В качестве альтернативы, максимальное количество попыток может быть определено в самом классе задания. Более подробную информацию о запуске работника очереди можно найти ниже .queue:work
Закрытие очереди
Вместо отправки класса задания в очередь, вы также можете отправить замыкание. Это отлично подходит для быстрых, простых задач, которые должны быть выполнены вне текущего цикла запроса:
$podcast = App\Podcast::find(1);
dispatch(function () use ($podcast) {
$podcast->publish();
});
При отправке Closures в очередь содержимое кода Closure криптографически подписывается, поэтому его нельзя изменить при передаче.
Запуск работника очереди
Laravel включает в себя работника очереди, который будет обрабатывать новые задания по мере их поступления в очередь. Вы можете запустить работника, используя команду Artisan. Обратите внимание, что после запуска команды она будет продолжаться до тех пор, пока она не будет остановлена вручную или вы не закроете свой терминал:queue:work
queue:work
php artisan queue:work
Чтобы процесс работал постоянно в фоновом режиме, вы должны использовать монитор процесса, такой как Supervisor, чтобы гарантировать, что работник очереди не перестанет работать.
queue:work
Помните, что работники очереди являются долгоживущими процессами и хранят загруженное состояние приложения в памяти. В результате они не заметят изменений в вашей кодовой базе после их запуска. Поэтому во время процесса развертывания обязательно перезапустите работников очереди .
Указание соединения и очереди
Вы также можете указать, какое подключение к очереди должен использовать работник. Имя соединения, переданное work
команде, должно соответствовать одному из соединений, определенных в вашем файле конфигурации:config/queue.php
php artisan queue:work redis
Вы можете еще больше настроить своего работника очереди, обрабатывая только определенные очереди для данного соединения. Например, если все ваши электронные письма обрабатываются в emails
очереди в вашем redis
подключении к очереди, вы можете выполнить следующую команду, чтобы запустить работника, который обрабатывает только эту очередь:
php artisan queue:work redis --queue=emails
Обработка одного задания
--once
Вариант может быть использован , чтобы поручить работнику обрабатывать только одно задание из очереди:
php artisan queue:work --once
Обработка всех заданий в очереди и выход
Эта опция может использоваться, чтобы проинструктировать работника обрабатывать все задания и затем корректно завершать работу. Эта опция может быть полезна при работе с очередями Laravel в контейнере Docker, если вы хотите закрыть контейнер после того, как очередь пуста:--stop-when-empty
php artisan queue:work --stop-when-empty
Ресурсы
Работники очереди демонов не «перезагружают» каркас перед обработкой каждого задания. Поэтому вы должны освобождать любые тяжелые ресурсы после завершения каждой работы. Например, если вы выполняете манипуляции с изображениями с помощью библиотеки GD, вы должны освободить память, imagedestroy
когда закончите.
Приоритеты очереди
Иногда вы можете расставить приоритеты в обработке ваших очередей. Например, в вашем вы можете установить по умолчанию для вашего подключения к . Однако иногда вы можете отправить задание в приоритетную очередь следующим образом:config/queue.php
queue
redis
low
high
dispatch((new Job)->onQueue('high'));
Чтобы запустить работника, который проверяет, что все high
задания очереди обрабатываются, прежде чем low
переходить к каким-либо заданиям в очереди, передайте в work
команду список имен очередей, разделенных запятыми :
php artisan queue:work --queue=high,low
Рабочие очереди и развертывание
Поскольку работники очереди являются долгоживущими процессами, они не получат изменения в вашем коде без перезапуска. Итак, самый простой способ развертывания приложения с использованием работников очереди - это перезапустить работников во время процесса развертывания. Вы можете корректно перезапустить всех рабочих, выполнив команду:queue:restart
php artisan queue:restart
Эта команда будет указывать всем работникам очереди изящно «умереть» после того, как они завершат обработку своего текущего задания, так что ни одно из существующих заданий не будет потеряно. Поскольку работники очереди умрут при выполнении команды, вы должны запустить диспетчер процессов, такой как Supervisor, для автоматического перезапуска работников очереди.queue:restart
Очередь использует кэш для хранения сигналов перезапуска, поэтому перед использованием этой функции необходимо убедиться, что драйвер кеша правильно настроен для вашего приложения.
Истечение срока работы и тайм-ауты
Срок действия
В вашем файле конфигурации каждое подключение очереди определяет опцию. Этот параметр указывает, сколько секунд соединение очереди должно ждать, прежде чем повторять работу, которая обрабатывается. Например, если значение установлено в , задание будет возвращено в очередь, если оно обрабатывалось в течение 90 секунд без удаления. Как правило, вы должны установить максимальное количество секунд, в течение которых ваши задания должны разумно занять время для завершения обработки.config/queue.php
retry_after
retry_after
90
retry_after
Единственное подключение к очереди, которое не содержит
retry_after
значения, - это Amazon SQS. SQS повторит задание в соответствии с Тайм-аутом видимости по умолчанию, который управляется в консоли AWS.
Тайм-аут работников
Команда Artisan предоставляет возможность выбора. Параметр определяет , как долго главный процесс очереди Laravel будет ждать , прежде чем убивать ребенок - очередь работника , который обрабатывает задание. Иногда дочерний процесс очереди может зависнуть по разным причинам, например, внешний HTTP-вызов не отвечает. Опция удаляет замороженные процессы, превысившие , что указанный срок:queue:work
--timeout
--timeout
--timeout
php artisan queue:work --timeout=60
Параметр retry_after
конфигурации и параметр --timeout
CLI различны, но работают вместе, чтобы гарантировать, что задания не будут потеряны и что задания будут успешно обработаны только один раз.
--timeout
Значение всегда должно быть по крайней мере на несколько секунд короче , чемretry_after
значение конфигурации. Это гарантирует, что работник, обрабатывающий заданное задание, всегда будет убит до повторного выполнения задания. Если ваш--timeout
вариант длиннее значения вашейretry_after
конфигурации, ваши задания могут быть обработаны дважды.
Продолжительность сна работника
Когда задания будут доступны в очереди, работник продолжит обрабатывать задания без задержки между ними. Однако эта sleep
опция определяет, как долго (в секундах) работник будет «спать», если новых рабочих мест не будет. Во время сна работник не будет обрабатывать новые задания - задания будут обрабатываться после того, как работник снова проснется.
php artisan queue:work --sleep=3
Конфигурация супервизора
Установка Supervisor
Supervisor - это монитор процессов для операционной системы Linux, который автоматически перезапустит ваш процесс в случае сбоя. Чтобы установить Supervisor в Ubuntu, вы можете использовать следующую команду:queue:work
sudo apt-get install supervisor
Если настройка Supervisor сама по себе кажется излишней, подумайте об использовании Laravel Forge , который автоматически установит и настроит Supervisor для ваших проектов Laravel.
Настройка супервизора
Файлы конфигурации супервизора обычно хранятся в каталоге. В этом каталоге вы можете создать любое количество файлов конфигурации, которые инструктируют супервизора, как следует отслеживать ваши процессы. Например, давайте создадим файл, который запускает и контролирует процесс:/etc/supervisor/conf.d
laravel-worker.conf
queue:work
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log
В этом примере numprocs
директива будет инструктировать Supervisor запускать 8 процессов и отслеживать все из них, автоматически перезапуская их в случае сбоя. Вы должны изменить часть директивы, чтобы отразить желаемое соединение с очередью.queue:work
queue:work sqs
command
Начальный руководитель
После того, как файл конфигурации был создан, вы можете обновить конфигурацию Supervisor и запустить процессы, используя следующие команды:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-worker:*
Для получения дополнительной информации о супервизоре, обратитесь к документации супервизора .
Работа с ошибочными рабочими местами
Иногда ваша работа в очереди не удастся. Не волнуйтесь, все не всегда идет как запланировано! В Laravel есть удобный способ указать максимальное количество попыток выполнения задания. После того, как задание превысило это количество попыток, оно будет вставлено в failed_jobs
таблицу базы данных. Чтобы создать миграцию для failed_jobs
таблицы, вы можете использовать команду:queue:failed-table
php artisan queue:failed-table
php artisan migrate
Затем, когда вы запускаете работника очереди , вы должны указать максимальное количество попыток выполнения задания с помощью --tries
переключателя в команде. Если вы не укажете значение для опции, задания будут выполняться бесконечно:queue:work
--tries
php artisan queue:work redis --tries=3
Кроме того, вы можете указать, сколько секунд Laravel должен подождать, прежде чем повторять попытку задания, которое не удалось, используя эту --delay
опцию. По умолчанию задание повторяется немедленно:
php artisan queue:work redis --tries=3 --delay=3
Если вы хотите настроить задержку повторения неудачного задания для каждого отдельного задания, вы можете сделать это, определив retryAfter
свойство для вашего класса заданий в очереди:
/**
* The number of seconds to wait before retrying the job.
*
* @var int
*/
public $retryAfter = 3;
Очистка после неудачных работ
Вы можете определить failed
метод непосредственно в своем классе заданий, позволяющий выполнять очистку для конкретного задания в случае сбоя. Это идеальное место для отправки оповещения вашим пользователям или отмены любых действий, выполненных заданием. То, Exception
что вызвало сбой задания, будет передано failed
методу:
<?php
namespace App\Jobs;
use Exception;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessPodcast implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* Create a new job instance.
*
* @param Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* Execute the job.
*
* @param AudioProcessor $processor
* @return void
*/
public function handle(AudioProcessor $processor)
{
// Process uploaded podcast...
}
/**
* The job failed to process.
*
* @param Exception $exception
* @return void
*/
public function failed(Exception $exception)
{
// Send user notification of failure, etc...
}
}
Неудачные вакансии
Если вы хотите зарегистрировать событие, которое будет вызываться при сбое задания, вы можете использовать этот метод. Это событие - отличная возможность уведомить вашу команду по электронной почте или Slack . Например, мы можем прикрепить обратный вызов к этому событию из того, что включено в Laravel:Queue::failing
AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Queue;
use Illuminate\Queue\Events\JobFailed;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Queue::failing(function (JobFailed $event) {
// $event->connectionName
// $event->job
// $event->exception
});
}
}
Повторная попытка неудачных заданий
Чтобы просмотреть все невыполненные задания, которые были вставлены в failed_jobs
таблицу базы данных, вы можете использовать команду Artisan:queue:failed
php artisan queue:failed
Команда выведет список идентификатора задания, соединения, очереди и времени отказа. Идентификатор задания можно использовать, чтобы повторить сбойное задание. Например, чтобы повторить неудачное задание с идентификатором , введите следующую команду:queue:failed
5
php artisan queue:retry 5
Чтобы повторить все неудачные задания, выполните команду и передайте в качестве идентификатора:queue:retry
all
php artisan queue:retry all
Если вы хотите удалить невыполненную работу, вы можете использовать команду:queue:forget
php artisan queue:forget 5
Чтобы удалить все неудачные задания, вы можете использовать команду:queue:flush
php artisan queue:flush
Игнорирование недостающих моделей
При внедрении модели Eloquent в задание она автоматически сериализуется перед помещением в очередь и восстанавливается при обработке задания. Однако, если модель была удалена, когда задание ожидало обработки работником, ваша работа может завершиться ошибкой с ModelNotFoundException
.
Для удобства вы можете выбрать автоматическое удаление заданий с отсутствующими моделями, установив для deleteWhenMissingModels
свойства задания следующее true
:
/**
* Delete the job if its models no longer exist.
*
* @var bool
*/
public $deleteWhenMissingModels = true;
Работа события
Использование before
и after
метод на Queue
фасаде , вы можете указать функции обратного вызова , которые должны выполняться до или после постановки задания в очереди обрабатывается. Эти обратные вызовы являются отличной возможностью для дополнительной регистрации или увеличения статистики для панели мониторинга. Как правило, вы должны вызывать эти методы у поставщика услуг . Например, мы можем использовать то, AppServiceProvider
что включено в Laravel:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\ServiceProvider;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Queue::before(function (JobProcessing $event) {
// $event->connectionName
// $event->job
// $event->job->payload()
});
Queue::after(function (JobProcessed $event) {
// $event->connectionName
// $event->job
// $event->job->payload()
});
}
}
Используя looping
метод на Queue
фасаде , вы можете указать обратные вызовы, которые выполняются до того, как работник попытается получить задание из очереди. Например, вы можете зарегистрировать Closure, чтобы откатить любые транзакции, которые были оставлены открытыми ранее неудачным заданием:
Queue::looping(function () {
while (DB::transactionLevel() > 0) {
DB::rollBack();
}
});
0 комментариев