Laravel Queue: как настроить фоновые задачи
Обработка тяжёлых операций (отправка писем, генерация отчётов, работа с внешними API) в реальном времени замедляет отклик приложения. Очереди Laravel позволяют вынести такие задачи в фоновый режим, улучшая производительность и пользовательский опыт.
Что такое очереди
Очередь — это механизм, который откладывает выполнение задач. Вместо того чтобы заставлять пользователя ждать, вы помещаете задачу в очередь, а специальный процесс (worker) обрабатывает её асинхронно.
Настройка драйвера
Laravel поддерживает несколько драйверов: sync, database, redis, beanstalkd, sqs. В продакшене для обеспечения высокой скорости рекомендую использовать Redis.
Настройте драйвер в .env:
QUEUE_CONNECTION=redis
Для драйвера database нужно создать таблицу:
php artisan queue:table
php artisan migrate
Конфигурация находится в config/queue.php, где можно настроить соединение и прочие параметры.
Создание задачи (Job)
Сгенерируйте класс задачи командой:
php artisan make:job SendWelcomeEmail
Пример реализации класса задачи:
<?php
namespace App\Jobs;
use App\Models\User;
use App\Mail\WelcomeMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
class SendWelcomeEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
// Количество попыток
public $tries = 3;
// Таймаут выполнения в секундах
public $timeout = 120;
// Задержка перед повтором при ошибке
public $backoff = 60;
public function __construct(public User $user)
{
}
public function handle(): void
{
Mail::to($this->user->email)
->send(new WelcomeMail($this->user));
}
// Обработка окончательного провала
public function failed(\Throwable $exception): void
{
\Log::error('Не удалось отправить письмо: ' . $exception->getMessage());
}
}
Отправка задачи в очередь
Отправить задачу в очередь можно несколькими способами:
use App\Jobs\SendWelcomeEmail;
// Простая отправка
SendWelcomeEmail::dispatch($user);
// С задержкой в 10 минут
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(10));
// В определённую очередь
SendWelcomeEmail::dispatch($user)->onQueue('emails');
// Условная отправка
SendWelcomeEmail::dispatchIf($user->isActive(), $user);
Запуск worker’а
Чтобы обрабатывать задачи, запустите процесс:
php artisan queue:work
Полезные опции:
// Обработка конкретной очереди с приоритетами
php artisan queue:work --queue=high,default,low
// Ограничение попыток и таймаут
php artisan queue:work --tries=3 --timeout=90
// Остановка после обработки задач (для тестов)
php artisan queue:work --stop-when-empty
После изменения кода задач нужно перезапускать воркер командой php artisan queue:restart, так как процесс держит код в памяти.
Приоритеты и несколько очередей
Разделяйте задачи по важности. Например, платежи — в очередь high, рассылки — в low:
ProcessPayment::dispatch($order)->onQueue('high');
SendNewsletter::dispatch($subscriber)->onQueue('low');
Worker обработает очереди в порядке указания.
Пакетная обработка (Batches)
Для групповых задач с отслеживанием прогресса используйте батчи:
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
$batch = Bus::batch([
new ImportUsers(1, 100),
new ImportUsers(101, 200),
new ImportUsers(201, 300),
])->then(function (Batch $batch) {
// Все задачи выполнены успешно
})->catch(function (Batch $batch, \Throwable $e) {
// Первая ошибка
})->finally(function (Batch $batch) {
// Завершение независимо от результата
})->dispatch();
Не забудьте создать таблицу для батчей:
php artisan queue:batches-table
php artisan migrate
Обработка проваленных задач
Создайте таблицу для неудачных задач:
php artisan queue:failed-table
php artisan migrate
Управление проваленными задачами:
// Просмотр списка
php artisan queue:failed
// Повторный запуск задачи по ID
php artisan queue:retry 5
// Повтор всех
php artisan queue:retry all
// Удаление
php artisan queue:forget 5
Supervisor для продакшена
В реальных проектах worker должен работать постоянно. Используйте Supervisor для автоматического перезапуска.
Пример конфига для Supervisor:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=4
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/worker.log
stopwaitsecs=3600
Параметр numprocs=4 запускает четыре параллельных процесса.
Заключение
Очереди Laravel — мощный инструмент для повышения производительности. Ключевые рекомендации:
- Используйте Redis в продакшене;
- Настраивайте tries, timeout и backoff для устойчивости;
- Разделяйте задачи по приоритетам;
- Обязательно используйте Supervisor для стабильной работы;
- Не забывайте перезапускать воркер после изменений.
Правильно настроенные фоновые задачи сделают ваше приложение быстрым и отзывчивым.