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.
Чек-лист
- Проверить, добавляются ли задачи в очередь.
- Проверить, запущен ли worker.
- Проверить PHP-версию в CLI.
- Посмотреть systemd или supervisor logs.
- Проверить Redis или DB-хранилище очереди.
- Найти зависшие и долго выполняющиеся задачи.
- Проверить memory usage worker.
- Настроить retries, ttr и логирование ошибок.
Очередь должна быть наблюдаемой. Если видно, сколько задач ждёт, какой worker работает, какие задачи падают и сколько длится обработка, проблема находится быстрее и не превращается в потерянные письма, заказы или остатки.
Комментарии (0)
Пока нет комментариев. Будьте первым!