Как организовать вынос ресурсоемкой задачи из основного кода с помощью очереди

«Как организовать вынос ресурсоемкой задачи из основного кода с помощью очереди» — вопрос из категории Архитектура, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В проектах, где были тяжелые операции (генерация отчетов, обработка изображений, массовая рассылка), я выносил их в фоновые задачи через очереди. Вот как это выглядело на практике:

Архитектура:

  1. Основное приложение (Producer) ставит задачу в очередь.
  2. Отдельный воркер-процесс (Consumer) в бесконечном цикле забирает задачи и выполняет их.

Пример с Laravel и Redis queue: Сначала создается job-класс:

// app/Jobs/GenerateReport.php
class GenerateReport implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $userId;

    public function __construct($userId) {
        $this->userId = $userId;
    }

    public function handle() {
        // Долгая логика генерации PDF-отчета
        $report = PDF::generateForUser($this->userId);
        // Сохранение и отправка уведомления пользователю
        Storage::put('reports/report.pdf', $report);
        Mail::to($this->user->email)->send(new ReportReady());
    }
}

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

// В контроллере
public function requestReport(Request $request) {
    GenerateReport::dispatch($request->user()->id);
    return response()->json(['message' => 'Report generation started']);
}

Воркер запускается командой php artisan queue:work.

Преимущества, которые я наблюдал:

  • Отзывчивость UI: Пользователь получает ответ сразу.
  • Устойчивость: Задачи переживают перезапуск приложения, если использовать надежный бэкенд очереди (Redis, RabbitMQ, базу данных).
  • Масштабирование: Можно запустить несколько воркеров на разных серверах для обработки пиковой нагрузки.