Skip to content

Очереди и фоновые задачи

Что делал на практике

  • выносил тяжёлые операции из синхронного HTTP-ответа в background jobs;
  • проектировал сценарии, где клиент получает pending-статус и отдельный идентификатор фоновой операции;
  • настраивал отдельные queue worker-процессы;
  • использовал Redis как инфраструктурный слой для очередей;
  • связывал фоновые задачи с прикладным состоянием операции в БД;
  • логировал жизненный цикл job и сопутствующих процессов;
  • учитывал retry / timeout / failure-сценарии;
  • связывал завершение фоновой задачи с последующей доставкой результата пользователю;
  • использовал очереди не только для jobs, но и для уведомлений.

Типовые сценарии и flow

Обычно выношу в очередь операции, которые:

  • занимают заметное время;
  • зависят от внешних ресурсов или файловой системы;
  • могут выполняться асинхронно без ухудшения UX;
  • нежелательно держать внутри открытого HTTP-запроса;
  • требуют отдельного контроля за retry и ошибками.

Из типовых сценариев:

  • генерация файлов и экспортов;
  • отправка email-уведомлений;
  • пост-обработка данных после пользовательского действия;
  • интеграционные и служебные процессы;
  • тяжёлые вычислительные или IO-bound операции.

Обычно flow выглядел так:

  • API не генерирует PDF синхронно, а создаёт export job;
  • клиент получает 202 Accepted, export_job_id и начальный статус;
  • прикладной handler создаёт запись о фоновой операции и отправляет конкретную job в очередь;
  • worker обрабатывает задачу отдельно от web-request;
  • в процессе задача переводится по статусам pendingprocessingready / failed;
  • после завершения результат сохраняется в storage и становится доступен для скачивания;
  • клиент получает статус и результат через polling, download или realtime flow.

Для фоновой операции обычно использовал:

  • уникальный идентификатор операции;
  • исходный статус (pending);
  • переход в processing при старте выполнения;
  • финальное состояние ready, completed или failed;
  • сохранённый результат или описание ошибки.

Worker и эксплуатация

Настраивал поведение worker-процессов с учётом повторных попыток и ограничений по времени выполнения.

  • количество tries;
  • timeout на выполнение задачи;
  • обработку ожидаемых и неожиданных ошибок;
  • различие между временным сбоем и окончательным провалом операции;
  • корректное обновление прикладного статуса при неуспехе.

Worker запускался отдельно и работал с настройками --tries=3, --timeout=120, --sleep=3, что отражает базовую эксплуатационную дисциплину для фоновых задач.

На практике это выражалось отдельным сервисом queue в docker-compose.yml, который запускает queue:work независимо от основного PHP-FPM контейнера.

  • независимый жизненный цикл worker-процесса;
  • возможность отдельно рестартовать обработчик очередей;
  • более предсказуемое поведение для тяжёлых задач;
  • более чистое разделение web- и background-нагрузки.

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

  • отправка email-уведомлений может выполняться асинхронно;
  • основное действие пользователя не блокируется ожиданием отправки письма;
  • уведомление проходит через тот же управляемый queue-механизм, что и остальные фоновые процессы.

Для фоновых задач отдельно логировал:

  • постановку задачи в очередь;
  • начало выполнения;
  • завершение;
  • ошибки и причины провала;
  • технический контекст операции.

Практические принципы

  • очередь должна быть частью пользовательского и прикладного сценария, а не просто способом вынести код из контроллера;
  • у долгих операций должен быть явный статус и идентификатор;
  • retry и timeout нужно задавать осознанно;
  • worker лучше держать отдельно от web-процесса;
  • фоновые задачи нужно логировать и наблюдать так же внимательно, как HTTP-запросы;
  • клиентский сценарий нужно проектировать с учётом асинхронности: pending, ожидание, повторная проверка, получение результата.

См. также

Сайт обновлен и проверен: