# Черги 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/uk/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/uk/kb/php-cli-vs-fpm-cron/). Діагностувати падіння найпростіше за логами самого воркера і за загальним логом помилок PHP — порядок розбору описано у статті [про розбір логів PHP](https://www.zevshost.net/uk/kb/php-logi-oshibok-razbor/).

## Чек-лист налаштування черг у проді

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

---

Джерело: https://www.zevshost.net/uk/kb/php-ocheredi-supervisor/
