# Очереди PHP и Supervisor: воркеры для Laravel и Symfony

> Supervisor для очередей PHP: конфиг воркера, автоперезапуск, лимит памяти и разбор частых причин зависших задач.

Очередь позволяет вынести медленную работу — отправку писем, генерацию отчётов, обработку загруженных файлов — из HTTP-запроса в фоновый процесс. И Laravel, и Symfony умеют класть задачи в очередь, но сам обработчик задач — это отдельный долгоживущий процесс PHP, за которым нужно следить. Именно для этого нужен Supervisor.

## Зачем нужен отдельный процесс-воркер

Команда вроде `php artisan queue:work` в Laravel или `messenger:consume` в Symfony запускается один раз и работает, пока её не остановят или пока процесс не упадёт из-за необработанного исключения. Без надзирателя такой процесс рано или поздно завершится, а задачи будут копиться в очереди без единого обработчика. Настройка самого Symfony на сервере разобрана в статье [про Symfony на VPS](https://www.zevshost.net/ru/kb/symfony-nastroika-vps/).

Supervisor — демон, который запускает указанные процессы, перезапускает их при падении и позволяет держать сразу несколько одинаковых воркеров для параллельной обработки очереди.

## Установка и базовый конфиг

```
sudo apt install supervisor
sudo mkdir -p /etc/supervisor/conf.d
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
```

Пример конфига для Laravel-очереди с несколькими воркерами:

```
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/app/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
directory=/var/www/app
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 | число параллельных воркеров на очередь |
| autorestart | true | перезапуск при падении процесса |
| stopwaitsecs | 3600 | время на завершение текущей задачи перед kill |
| max-time / --time-limit | 3600 | плановый перезапуск воркера раз в час |

Плановый перезапуск воркера важен: PHP-процесс, который живёт часами, постепенно накапливает память из-за утечек в сторонних библиотеках. Раз в час Supervisor просто поднимает свежую копию процесса вместо старой.

## Команды управления и применения конфига

- `supervisorctl reread` — Supervisor видит новый или изменённый файл конфига в `conf.d`.
- `supervisorctl update` — применяет изменения: запускает новые программы, останавливает удалённые.
- `supervisorctl restart laravel-worker:*` — перезапускает все воркеры группы после деплоя нового кода.
- `supervisorctl status` — показывает состояние каждого воркера и время его последнего запуска.

## Частые причины зависших и потерянных задач

После деплоя нового релиза старые воркеры продолжают работать со старым кодом в памяти, пока их не перезапустят вручную через `supervisorctl restart` — это стоит добавить в скрипт деплоя как обязательный шаг. Ещё одна частая причина — воркер держит соединение с базой данных, которое MySQL обрывает по таймауту простоя, и следующая задача падает с ошибкой "MySQL server has gone away". Для CLI-запусков воркеров полезно понимать разницу с обработкой запросов через FPM — она описана в статье [про PHP CLI и FPM](https://www.zevshost.net/ru/kb/php-cli-vs-fpm-cron/). Диагностировать падения проще всего по логам самого воркера и по общему логу ошибок PHP — порядок разбора описан в статье [про разбор логов PHP](https://www.zevshost.net/ru/kb/php-logi-oshibok-razbor/).

## Чек-лист настройки очередей на проде

1. Задайте `--tries` и `--max-time` в команде воркера, чтобы зависшая задача не блокировала очередь навсегда.
2. Добавьте `supervisorctl restart` в скрипт деплоя сразу после обновления кода на сервере.
3. Настройте отдельный лог для воркеров и мониторинг числа задач в очереди, чтобы заметить рост очереди раньше пользователей.

---

Источник: https://www.zevshost.net/ru/kb/php-ocheredi-supervisor/
