Yii2 queue перестала обрабатывать задачи: где искать причину

Очередь Yii2 обычно ломается не громко, а тихо. Сайт открывается, заказы создаются, менеджеры работают, но фоновые задачи перестают выполняться: письма не уходят, остатки не обновляются, импорт завис, уведомления не отправлены. Проблема обнаруживается только тогда, когда накопилось достаточно последствий.

Разбирать такую ситуацию нужно по цепочке: задача добавляется в очередь, worker запущен, хранилище очереди доступно, задача не падает с ошибкой, логи пишутся, повторные попытки настроены.

Понять, задачи добавляются или нет

Сначала нужно отделить две проблемы. Первая — приложение не кладёт задачи в очередь. Вторая — задачи есть, но worker их не забирает.

Yii::$app->queue->push(new SendEmailJob([
    'email' => $email,
]));

Если используется Redis, DB или RabbitMQ, нужно посмотреть фактическое хранилище. Для DB-очереди можно проверить таблицу queue.

SELECT status, COUNT(*)
FROM queue
GROUP BY status;

Если новых задач нет, проблема выше: код не дошёл до push, условие не сработало, транзакция откатилась или возникла ошибка до постановки задачи.

Проверить worker

Для yii2-queue задачи обрабатывает отдельный процесс. Он может быть запущен через console-команду, systemd, supervisor или cron.

ps aux | grep "yii queue"
systemctl status site-queue
supervisorctl status

Если worker не запущен, очередь будет копиться. Если запущено слишком много worker без контроля, можно получить гонки и лишнюю нагрузку.

Версия PHP в консоли

Сайт может работать на PHP 8.2, а worker запускаться через старый php из CLI. Это частая причина ошибок после обновления сервера.

php -v
which php

В systemd unit лучше указывать полный путь:

ExecStart=/usr/bin/php8.2 /var/www/site.ru/yii queue/listen --verbose

Логи systemd или supervisor

Если worker падает сразу после старта, причина обычно есть в логах.

journalctl -u site-queue -n 150 --no-pager

Для supervisor:

supervisorctl tail site-queue stderr
supervisorctl tail site-queue stdout

Без логов очередь превращается в чёрный ящик. В unit или supervisor-конфиге нужно явно указать вывод.

Зависшая задача

Одна тяжёлая задача может занять worker надолго. В это время остальные задачи будут ждать. Особенно часто так происходит с импортом, внешними API без timeout или обработкой больших файлов.

Внутри job нужно логировать старт, завершение, ID сущности и длительность.

Yii::info([
    'job' => static::class,
    'order_id' => $this->orderId,
    'event' => 'start',
], 'queue');

Redis или другое хранилище

Если очередь хранится в Redis, нужно проверить доступность Redis, выбранную базу, память и ключи.

redis-cli ping
redis-cli info memory
redis-cli keys "*queue*"

Команду keys на production с большим Redis нужно использовать осторожно. Лучше знать точные ключи очереди.

Memory leak

Долгоживущий queue/listen может накапливать память из-за кода задач, библиотек или больших данных. Тогда worker постепенно раздувается и падает.

ps -o pid,pmem,rss,cmd -p <PID>

Если проблема подтверждается, можно ограничить время жизни процесса, обрабатывать задачи пакетно или использовать queue/run по расписанию для некоторых типов задач.

Retries и failed jobs

Задача не должна бесконечно падать без следов. Нужно настроить число попыток и логировать финальную ошибку.

public function getTtr()
{
    return 300;
}

public function canRetry($attempt, $error)
{
    return $attempt < 3;
}

Если ошибка постоянная, retry только создаёт шум. Если временная — retry помогает пережить сбой внешнего API.

Чек-лист

  1. Проверить, добавляются ли задачи в очередь.
  2. Проверить, запущен ли worker.
  3. Проверить PHP-версию в CLI.
  4. Посмотреть systemd или supervisor logs.
  5. Проверить Redis или DB-хранилище очереди.
  6. Найти зависшие и долго выполняющиеся задачи.
  7. Проверить memory usage worker.
  8. Настроить retries, ttr и логирование ошибок.

Очередь должна быть наблюдаемой. Если видно, сколько задач ждёт, какой worker работает, какие задачи падают и сколько длится обработка, проблема находится быстрее и не превращается в потерянные письма, заказы или остатки.

Комментарии (0)

Пока нет комментариев. Будьте первым!