Laravel Queue: как настроить фоновые задачи

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 для стабильной работы;
  • Не забывайте перезапускать воркер после изменений.

Правильно настроенные фоновые задачи сделают ваше приложение быстрым и отзывчивым.