Supervisor: как я управляю фоновыми процессами

Веб-приложение не ограничивается только обработкой 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 - никаких ручных правок на сервере.


Обсудить пост:

🔥 И не забудь подписаться :)