Веб-приложение не ограничивается только обработкой HTTP-запросов. Рано или поздно появляются задачи, которые нужно выполнять в фоне.
- Очереди и воркеры
- Демоны, которые слушают события
- Периодические задачи (кроны, но которые должны быть всегда запущены)
И тут возникает вопрос: кто будет следить за тем, чтобы эти процессы не упали?
Ответ - Supervisor.
Что такое Supervisor
Supervisor - это система контроля процессов для Unix-систем.
Он:
- Запускает процессы
- Следит за ними
- Перезапускает, если упали
- Хранит логи
- Позволяет управлять процессами через команды
Проще говоря: ты описываешь процесс один раз - Supervisor делает так, чтобы он всегда работал.
Как я устанавливаю Supervisor
Способы установки есть разные. Для своего проекта я пошёл по пути, который мне нравится больше всего - встроил Supervisor в Docker-образ.
Так я получаю готовую среду, где всё уже настроено и работает. Не нужно помнить, установлен ли Supervisor на сервере, не нужно править системные конфиги.
Вот мой Dockerfile:
FROM alpine:3.14
RUN apk add --no-cache \
autoconf \
rabbitmq-c-dev \
tzdata \
php7 \
php7-curl \
php7-redis \
php7-amqp \
php7-json \
php7-iconv \
php7-mbstring \
php7-pdo_mysql \
php7-xml \
php7-posix \
php7-pcntl \
zlib zlib-dev \
supervisor
RUN mkdir -p /var/log && chmod ugo+rw /var/log && \
mkdir -p /var/cache/app && chmod ugo+rw /var/cache/app && \
mkdir -p /var/log/supervisor && chmod ugo+rw /var/log/supervisor && \
mkdir -p /etc/supervisor/conf.d && chmod ugo+rw /var/log/supervisor
COPY ./supervisord.conf /etc/supervisor/supervisord.conf
WORKDIR /var/www
ENTRYPOINT ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/supervisord.conf"]
Что здесь происходит:
- Устанавливаем PHP, нужные расширения и Supervisor
- Создаём директории для логов с правильными правами
- Копируем готовый конфиг Supervisor
- Запускаем Supervisor в foreground-режиме (-n) — это обязательно для Docker
Нюансы, о которых стоит знать
1. Логи нужно ротировать
Supervisor пишет логи в файлы. Если их не ротировать - они будут расти вечно.
Делаем так:
stdout_logfile_maxbytes=50MB # Максимальный размер файла
stdout_logfile_backups=10 # Сколько старых логов хранить
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10
stdout_logfile_maxbytes=50MB - Как только лог-файл достигнет 50 МБ, Supervisor его переименует и начнёт новый
stdout_logfile_backups=10 - Хранит 10 старых файлов (app.log.1, app.log.2, ..., app.log.10)
Если хочешь отключить логирование в файл:
Отключать логи не советую никогда!
stdout_logfile=/dev/null
stderr_logfile=/dev/null
2. Выход с кодом 0 и 1
Supervisor считает, что если процесс завершился с кодом 0 - он завершился успешно и его не нужно перезапускать.
Для бесконечных процессов это не подходит. Я стараюсь писать единообразно для supervisord,
учитываю эту особенность: не завершаю процесс, если всё хорошо - только в случае исключения, чтобы избежать
зацикливания. И включаю опцию autorestart=true.
[program:app-consume-matchlist]
command=php /var/www/console.php app:consume matchlist
directory=/var/www
autorestart=true
В моём примере есть конструкция autorestart=true, которая говорит: «запускай всегда». Но если процесс падает постоянно, Supervisor перестаёт его поднимать, чтобы не тратить ресурсы.
Это даёт контроль над тем, когда процесс должен перезапускаться, а когда нет.
Supervisord очень гибкий в плане настроек, советую почитать документацию, чтобы изучить все возможности. Например, параметры startretries и startsecs позволяют тонко настроить поведение при падениях.
3. Supervisor не умеет распределять нагрузку
Если нужно запустить 10 воркеров - просто укажи numprocs=10. Supervisor сам запустит 10 процессов, но не будет балансировать между ними.
[program:app-scout]
command=php /var/www/console.php app:scout %(process_num)02d
numprocs=10
process_name=%(process_num)02d
...
🎯 Итог
Supervisor - это простой и надёжный способ управлять фоновыми процессами.
Особенно удобно использовать его в связке с Docker для небольших проектов, где не хочется поднимать сложные системы оркестрации.
Готовый образ с Supervisor даёт компактное решение, которое можно развернуть одной командой. Всё работает из коробки, а конфиги лежат в Git - никаких ручных правок на сервере.
Обсудить пост:
- Max → https://max.ru/id616507661604_biz
- Telegram → https://t.me/buriy_dev
🔥 И не забудь подписаться :)