Сигналы и перезагрузка

pg_doorman реагирует на четыре POSIX-сигнала: SIGHUP, SIGINT, SIGUSR2 и SIGTERM. Каждый делает одну конкретную вещь.

Краткая справка

СигналЭффектСуществующие соединенияКогда применять
SIGHUPПерезагрузить конфиг с диска.Сохраняются.Подкрутить пулы, ротировать серверные TLS-сертификаты, отредактировать pg_hba.conf.
SIGTERMПлавное завершение работы.Дренируются до простоя, затем закрываются.Остановка сервиса.
SIGUSR2Плавное обновление бинарника.Мигрируют в новый процесс.Замена бинарника без простоя.
SIGINTЗависит от TTY (см. ниже).По-разному.Ctrl+C при разработке; устарело для production.

Перезагрузка (SIGHUP)

kill -HUP $(pidof pg_doorman)

Перечитывает файл конфига и применяет изменения. Что перезагружается:

  • Определения пулов (добавлены, удалены, изменён размер).
  • Списки пользователей, пароли, блоки auth_query.
  • Правила pg_hba.conf (файл или встроенное содержимое).
  • Серверные TLS-сертификаты и CA-бандлы (подмена без блокировок; существующие TLS-соединения сохраняют исходный контекст).
  • Публичные ключи Talos и JWT.
  • Уровень логирования и формат логов.

Что не перезагружается:

  • general.host, general.port — слушающий сокет фиксируется при старте.
  • Клиентские TLS-сертификаты — нужен перезапуск процесса или используйте обновление бинарника.
  • Число рабочих потоков и параметры рантайма Tokio.

После перезагрузки SHOW CONFIG отображает новые значения. Существующие клиентские соединения не перепроверяются по новому pg_hba.conf — только новые соединения.

Плавное завершение работы (SIGTERM)

kill -TERM $(pidof pg_doorman)

pg_doorman:

  1. Прекращает принимать новые соединения.
  2. Закрывает простаивающие соединения с бэкендом.
  3. Логирует, сколько клиентов ещё в транзакциях.
  4. Ждёт до shutdown_timeout (по умолчанию 10 с), пока клиенты завершат работу.
  5. Выходит.

shutdown_timeout — жёсткий потолок. Клиенты, всё ещё находящиеся в транзакциях по его истечении, получают закрытие соединения.

general:
  shutdown_timeout: "30s"

Для systemd установите TimeoutStopSec больше, чем shutdown_timeout, чтобы systemd не отправил SIGKILL, пока pg_doorman ещё дренирует.

Обновление бинарника (SIGUSR2)

kill -USR2 $(pidof pg_doorman)

Рекомендуемый способ заменить бинарник, не теряя клиентов:

  1. Замените бинарник на диске новой версией.
  2. Отправьте SIGUSR2 работающему процессу.
  3. Текущий процесс порождает дочерний с новым бинарником, передаёт ему слушающий сокет и продолжает обслуживать существующих клиентов до их завершения.
  4. Новые клиенты сразу подключаются к дочернему процессу.
  5. Старый процесс выходит, когда последняя клиентская транзакция завершится (или по shutdown_timeout).

Дочерний процесс отправляет sd_notify MAINPID=<new_pid>, чтобы юниты systemd с Type=notify бесшовно обновили свой главный PID.

Полный протокол, миграцию TLS и откат смотрите в Binary Upgrade.

SIGINT (Ctrl+C)

SIGINT зависит от контекста:

  • На переднем плане с TTY (разработка, cargo run): только плавное завершение работы.
  • В режиме демона или без TTY (legacy production): запускает обновление бинарника и плавное завершение работы, как SIGUSR2.

Legacy-путь обновления через SIGINT существует ради обратной совместимости с инсталляциями, которые отправляют SIGINT из init-скриптов. Новые инсталляции должны явно использовать SIGUSR2 для обновления и SIGTERM для остановки.

Интеграция с systemd

pg_doorman поддерживает Type=notify. Поставляемый юнит pg_doorman.service запускает бинарник в основном процессе и уведомляет systemd через sd_notify:

[Service]
Type=notify
ExecStart=/usr/bin/pg_doorman /etc/pg_doorman/pg_doorman.yaml
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGTERM
TimeoutStopSec=60
Restart=on-failure

sd_notify READY=1 отправляется после привязки слушающего сокета и инициализации пулов. sd_notify MAINPID=<child> отправляется при обновлении бинарника, чтобы systemd корректно отслеживал новый процесс.

Если переходите с Type=forking + --daemon, уберите --daemon и переключитесь на Type=notify — меньше движущихся частей и корректное отслеживание готовности. Старые инсталляции с --daemon продолжают работать, но не получают преимуществ sd_notify.

Режим демона

pg_doorman --daemon ответвляется в фон и пишет PID в daemon_pid_file (по умолчанию /tmp/pg_doorman.pid). Под systemd предпочитайте Type=notify вместо --daemon.

general:
  daemon_pid_file: "/var/run/pg_doorman.pid"

Куда дальше

  • Binary Upgrade — полный протокол обновления с миграцией TLS.
  • Troubleshooting — что проверить, когда перезагрузка не подхватывает изменения.
  • TLS — семантика перезагрузки серверных сертификатов по SIGHUP.