diff --git a/documentation/en/src/comparison.md b/documentation/en/src/comparison.md index 26aa0b4a0..ef8655862 100644 --- a/documentation/en/src/comparison.md +++ b/documentation/en/src/comparison.md @@ -35,11 +35,11 @@ See [Authentication](authentication/overview.md). | Server-side TLS to PostgreSQL (`disable`, `allow`, `require`, `verify-ca`, `verify-full`) | Yes (5 modes) | Yes (`server_tls_*`, 6 modes incl. `prefer`) | No | | mTLS to PostgreSQL (client cert sent to backend) | Yes (`server_tls_certificate` + `server_tls_private_key`) | Yes (`server_tls_key_file` + `server_tls_cert_file`) | No | | Hot reload of server-side TLS certificates | Yes (`SIGHUP`) | Yes (via `RELOAD` / `SIGHUP`, "new file contents will be used for new connections") | No | -| Hot reload of client-facing TLS certificates | No (requires restart or binary upgrade) | Yes (via `RELOAD` / `SIGHUP`) | No | +| Hot reload of client-facing TLS certificates | No (`SIGHUP` unsupported; handoff loads new files for new connections only) | Yes (via `RELOAD` / `SIGHUP`) | No | | Minimum TLS version configurable | Yes (defaults to TLS 1.2) | Yes (`tls_protocols`, default `tlsv1.2,tlsv1.3`) | Configurable, defaults differ | | Direct TLS handshake (PostgreSQL 17, no `SSLRequest`) | No | Yes (since 1.25) | No | | TLS 1.3 cipher control | No | Yes (since 1.25, `client_tls13_ciphers`/`server_tls13_ciphers`) | No | -| TLS session migration across binary upgrade | Yes (`tls-migration` build, Linux, opt-in) | No (TLS connections are dropped during online restart) | No | +| TLS session migration across binary upgrade | Yes (Linux `tls-migration` build, same cert/key) | No (TLS connections are dropped during online restart) | No | See [TLS](guides/tls.md). @@ -125,7 +125,7 @@ See [Prometheus metrics reference](reference/prometheus.md), [Admin commands](ob | Feature | PgDoorman | PgBouncer | Odyssey | | --- | :-: | :-: | :-: | -| Binary upgrade with session migration (TCP socket, cancel keys, prepared cache) | Yes (`SCM_RIGHTS`, plus TLS state with the `tls-migration` build) | No: `-R` deprecated since 1.20; `so_reuseport` rolling restart drains old sessions in place | No: `SIGUSR2` + `bindwith_reuseport` drains old sessions in place | +| Binary upgrade with session migration (TCP socket, cancel keys, prepared cache) | Yes (`SCM_RIGHTS`, plus TLS state with Linux `tls-migration` and same cert/key) | No: `-R` deprecated since 1.20; `so_reuseport` rolling restart drains old sessions in place | No: `SIGUSR2` + `bindwith_reuseport` drains old sessions in place | | Configuration format | YAML or TOML | INI | Own format (lex/yacc) | | Human-readable durations and sizes (`30s`, `1h`, `256MB`) | Yes | No (integer microseconds / bytes) | No | | Config test mode (`pg_doorman -t`) | Yes | No | No | diff --git a/documentation/en/src/guides/tls.md b/documentation/en/src/guides/tls.md index 7b168ea92..7a2ad6b0a 100644 --- a/documentation/en/src/guides/tls.md +++ b/documentation/en/src/guides/tls.md @@ -34,7 +34,7 @@ The certificate may be self-signed for development; production deployments typic Client-side certificates are loaded at startup. Changing them requires a process restart. There is no `SIGHUP` reload for client-side TLS. -For zero-downtime certificate rotation, see [Binary Upgrade](../tutorials/binary-upgrade.md). +Hot process handoff can load a new certificate and key for new inbound TLS connections, but it is not seamless rotation for sessions that are already open. To migrate TLS sessions, both processes must use the same `tls_certificate` and `tls_private_key`, and PgDoorman must run as a Linux build with `tls-migration`; if those files change, TLS clients drain and reconnect. ### Cipher policy @@ -108,5 +108,5 @@ See [Prometheus reference](../reference/prometheus.md). ## Where to next - New cluster setup? See [Installation](../tutorials/installation.md). -- Rotating certificates? See [Binary Upgrade](../tutorials/binary-upgrade.md) and [Signals](../operations/signals.md). +- Rotating certificates? See [Binary Upgrade](../tutorials/binary-upgrade.md) and [Signals](../operations/signals.md). Client-facing TLS certificate rotation is not seamless for already-open TLS sessions. - Hardening an existing deployment? Combine with [pg_hba.conf](../authentication/hba.md): force `hostssl` for non-local connections. diff --git a/documentation/en/src/index.md b/documentation/en/src/index.md index 4958866d9..b3407acbe 100644 --- a/documentation/en/src/index.md +++ b/documentation/en/src/index.md @@ -6,52 +6,52 @@ A multi-threaded PostgreSQL connection pooler written in Rust. Drop-in replaceme ## Headline features -```admonish success title="Built-in diagnostic console" -A diagnostic console embedded in the pg_doorman binary, served on the same port as `/metrics`. It gives operators the incident view that `/metrics` and the psql admin console expose only in pieces: pool saturation, latency percentiles, SQLSTATE breakdowns, long-running queries, prepared-cache and query-interner state, process memory, cgroup limits, per-worker CPU, and a live log tail. +```admonish success title="Anonymous Parse Caching" +In the extended protocol, many drivers send short parameterised queries as an unnamed `Parse`. PgDoorman rewrites that `Parse` on the PostgreSQL side to an internal `DOORMAN_` name and keeps the mapping in the pool. Later `Bind`s for the same query shape reuse prepared backend state. -The console is for live diagnosis, not a replacement for long-term Prometheus/Grafana monitoring. +That cuts repeated PostgreSQL planner work on hot OLTP paths without application changes. PgBouncer 1.21+ and Odyssey can track named prepared statements, but they forward anonymous `Parse` unchanged; PgDoorman covers the driver-default case. -Pause / Resume / Reconnect / Reload act from the same page, scoped per pool or globally. Read-only otherwise. The console activates only when `[web].ui = true` and `general.admin_password` is non-default; a fresh install with the placeholder password keeps the listener at `/metrics` only and logs a `WARN`. +The cache is bounded: anonymous entries expire after idle timeout, and named entries are freed after their last reference. `SHOW INTERNER` exposes query-text memory; Prometheus metrics expose hits, misses, and evictions. -[Read more →](guides/web-ui.md) +[Read more →](tutorials/prepared-statements.md) ``` ```admonish success title="Pool Coordinator" -PgDoorman caps total backend connections per database. When `max_db_connections` is reached, the coordinator evicts an idle connection from the user with the most spare capacity, ranking candidates by p95 transaction time so the slowest pools yield first. A reserve pool absorbs short bursts; per-user `min_guaranteed_pool_size` keeps critical workloads off the eviction list. +When several user pools share one database, the global limit should protect PostgreSQL, not just queue clients. PgDoorman enforces `max_db_connections`: once the cap is reached, the coordinator closes an idle connection from a pool with spare capacity and gives the slot to a client waiting for a backend. + +Donors are ranked by excess idle connections. On a tie, the pool with the higher p95 transaction time yields first: fast pools keep more reuse chances, while evicting an idle connection from a slower pool hurts less. The reserve pool absorbs short bursts, and `min_guaranteed_pool_size` protects critical workloads from eviction. -PgBouncer's `max_db_connections` has no eviction or fairness — when the cap is reached, clients queue until existing connections close on their own idle timeout. Odyssey has no equivalent setting. +PgBouncer's `max_db_connections` sets a shared cap, but it does not redistribute already-open idle connections between pools. Odyssey has no direct equivalent. [Read more →](concepts/pool-coordinator.md) ``` ```admonish success title="Patroni-assisted Fallback" -When PgDoorman runs next to PostgreSQL on the same machine and a Patroni switchover kills the local backend, PgDoorman polls the Patroni REST API (`GET /cluster`), picks a live cluster member (priority `sync_standby` → `replica`), and routes new connections there. The local backend enters cooldown; fallback connections inherit a short lifetime so the pool returns to local as soon as it recovers. +When PgDoorman runs next to PostgreSQL and the local server disappears during a Patroni switchover, new backend connections temporarily go to another live cluster member. PgDoorman chooses the target through the Patroni REST API (`GET /cluster`): `sync_standby` first, then `replica`. -Set `patroni_api_urls` and `fallback_cooldown` in `[general]` and it applies to every pool. No HAProxy or `consul-template` in front of the pooler. +The local server enters cooldown, and fallback connections get a short lifetime. Once the local node is reachable again, the pool returns to it without a separate HAProxy or `consul-template` in front of the pooler. `patroni_api_urls` and `fallback_cooldown` are configured in `[general]`. [Read more →](tutorials/patroni-assisted-fallback.md) ``` -```admonish success title="Graceful Binary Upgrade" -Update PgDoorman without stopping the listener. Idle client sessions can move to the new process, which avoids a reconnect wave and reduces repeated `auth`/SCRAM handshakes against PostgreSQL. Clients inside a transaction stay on the old process until they go idle. +```admonish success title="Hot Process Handoff with Session Migration" +Before `SIGUSR2` or `UPGRADE`, operators can replace the binary and config on disk. PgDoorman validates that pair with `-t`, starts a child process with it, passes the listening socket to the child, and keeps the old process serving existing clients while eligible sessions migrate. -On `SIGUSR2` the old process hands each idle client's TCP socket to the new one through `SCM_RIGHTS` — same socket, no reconnect — together with cancel keys and the prepared-statement cache. Clients inside a transaction finish on the old process and migrate as soon as they go idle. With the `tls-migration` build (Linux, opt-in) the OpenSSL cipher state moves too, so TLS sessions survive without a re-handshake. +The new process receives `connection_id`, the cancel key, PostgreSQL session parameters, backend authentication state, and the client prepared-statement cache. From the application's point of view the connection stays open: no reconnect, no repeated `auth`/SCRAM, and no lost prepared statements. If the new backend connection has not prepared a statement yet, PgDoorman sends the needed `Parse` on the first `Bind`. -PgBouncer's online restart (`-R`, deprecated since 1.20; or `so_reuseport` rolling restart) and Odyssey's online restart (`SIGUSR2` + `bindwith_reuseport`) work the same way as each other: the new process picks up new connections, the old one drains until its existing clients disconnect on their own. Sessions, prepared statements, and TLS state never move between processes. +In foreground mode, non-TLS TCP sessions move through `SCM_RIGHTS`. TLS sessions migrate only on a Linux build with `tls-migration` and the same `tls_certificate`/`tls_private_key`; distro packages and the Docker image are built without it, so TLS clients drain. Clients inside a transaction stay on the old process and move after `COMMIT` or `ROLLBACK`. PgBouncer (`-R`, deprecated since 1.20, or rolling restart via `so_reuseport`) and Odyssey (`SIGUSR2` + `bindwith_reuseport`) leave old sessions in the old process until clients disconnect. [Read more →](tutorials/binary-upgrade.md) ``` -```admonish success title="Anonymous Parse Caching" -In extended protocol, many drivers send short parameterised queries as `Parse` with an empty statement name. Without a remap, that hot path keeps paying PostgreSQL planner CPU and repeated backend `Parse` work on every reuse. - -PgDoorman rewrites the empty name to an internal `DOORMAN_` on the backend and keeps the mapping in the pool. PostgreSQL sees a named prepared statement, so later `Bind`s for the same query shape can reuse prepared backend state across one client and across clients sharing the pool. The primary value is performance: less planner work and fewer backend Parses on repeated OLTP queries. +```admonish success title="Built-in Diagnostic Console" +PgDoorman serves the web console on the same address and port as `/metrics`. It is a local incident panel, not a replacement for long-term Prometheus/Grafana monitoring. -PgBouncer (1.21+) and Odyssey support prepared statements in transaction mode, but only for **named** statements; an anonymous `Parse` is forwarded as-is and re-planned on every call. PgDoorman is the one that rewrites it. +One screen shows pool saturation, p95/p99 query, transaction, and checkout latency, SQLSTATE errors, long-running queries, prepared-statement and query-interner state, the log tail, CPU by `tokio-worker`, and process memory (`jemalloc`, `/proc/self/status`, text/libs, stacks, swap). -To keep that optimization operationally safe, the cache is bounded and observable. Anonymous entries time out on idle, named entries reclaim once nothing references them, `SHOW INTERNER` exposes interner size, and Prometheus metrics expose hits, misses, and evictions. +The console can run Pause, Resume, Reconnect, and Reload for one pool or the whole instance. Other views are read-only. The UI is enabled only when `[web].ui = true` and `general.admin_password` is set to a non-placeholder value; otherwise PgDoorman keeps only `/metrics` and logs a `WARN`. -[Read more →](tutorials/prepared-statements.md) +[Read more →](guides/web-ui.md) ``` ## Why PgDoorman @@ -74,7 +74,7 @@ To keep that optimization operationally safe, the cache is bounded and observabl | Patroni-assisted fallback (built-in) | Yes | No | No | | Pre-replacement on `server_lifetime` expiry | Yes | No | No | | Stale backend detection inside a transaction | Yes (immediate `08006`) | No (waits for TCP keepalive) | No (waits for TCP keepalive) | -| Binary upgrade with session migration | Yes (`SCM_RIGHTS`, TLS state opt-in) | No (sessions stay on old process) | No (sessions stay on old process) | +| Hot process handoff with idle-session migration | Yes, via `SCM_RIGHTS`; TLS state with `tls-migration` and same cert/key | No (sessions stay on old process) | No (sessions stay on old process) | | Backend TLS to PostgreSQL | Yes (5 modes, hot reload via `SIGHUP`) | Yes (`server_tls_*`, hot reload via `RELOAD`) | No | | Auth: SCRAM passthrough (no plaintext password) | Yes (`ClientKey` extracted from proof) | Yes (encrypted SCRAM secret via `auth_query`/`userlist.txt`, since 1.14) | Yes | | Auth: JWT (RSA-SHA256) | Yes | No | No | diff --git a/documentation/en/src/tutorials/binary-upgrade.md b/documentation/en/src/tutorials/binary-upgrade.md index 59d4b576e..3d6947f8e 100644 --- a/documentation/en/src/tutorials/binary-upgrade.md +++ b/documentation/en/src/tutorials/binary-upgrade.md @@ -15,7 +15,8 @@ rolling restart) and Odyssey's online restart (`SIGUSR2` + picks up new connections, the old one drains until its existing clients disconnect. Sessions, prepared statements, and TLS state never cross processes. pg_doorman migrates the live socket via `SCM_RIGHTS`, plus the -cipher state with the `tls-migration` build (Linux, opt-in). +cipher state with the `tls-migration` build when both processes use the +same client-facing certificate and key (Linux, opt-in). ``` ## Quick start diff --git a/documentation/ru/src/SUMMARY.md b/documentation/ru/src/SUMMARY.md index 8ccd83e8d..3090acb22 100644 --- a/documentation/ru/src/SUMMARY.md +++ b/documentation/ru/src/SUMMARY.md @@ -40,7 +40,7 @@ # Эксплуатация -- [Плавное обновление бинаря](tutorials/binary-upgrade.md) +- [Горячая замена процесса с переносом сессий](tutorials/binary-upgrade.md) - [Сигналы и перезагрузка](operations/signals.md) - [Fastpath и large objects](operations/fastpath-large-objects.md) - [Мониторинг query interner](operations/monitoring-interner.md) diff --git a/documentation/ru/src/comparison.md b/documentation/ru/src/comparison.md index 4eb73185a..f0fec6ccc 100644 --- a/documentation/ru/src/comparison.md +++ b/documentation/ru/src/comparison.md @@ -35,11 +35,11 @@ PgCat намеренно опущен: у него центр тяжести — | Server-side TLS к PostgreSQL (`disable`, `allow`, `require`, `verify-ca`, `verify-full`) | Да (5 режимов) | Да (`server_tls_*`, 6 режимов вкл. `prefer`) | Нет | | mTLS к PostgreSQL (отправка клиентского сертификата на backend) | Да (`server_tls_certificate` + `server_tls_private_key`) | Да (`server_tls_key_file` + `server_tls_cert_file`) | Нет | | Hot reload server-side TLS-сертификатов | Да (`SIGHUP`) | Да (через `RELOAD` / `SIGHUP`, "new file contents will be used for new connections") | Нет | -| Hot reload client-facing TLS-сертификатов | Нет (требуется restart или binary upgrade) | Да (через `RELOAD` / `SIGHUP`) | Нет | +| Hot reload client-facing TLS-сертификатов | Нет (требуется restart или горячая замена процесса) | Да (через `RELOAD` / `SIGHUP`) | Нет | | Минимальная версия TLS настраивается | Да (по умолчанию TLS 1.2) | Да (`tls_protocols`, default `tlsv1.2,tlsv1.3`) | Настраивается, дефолты другие | | Direct TLS handshake (PostgreSQL 17, без `SSLRequest`) | Нет | Да (с 1.25) | Нет | | Контроль TLS 1.3 cipher suites | Нет | Да (с 1.25, `client_tls13_ciphers`/`server_tls13_ciphers`) | Нет | -| Миграция TLS-сессии при binary upgrade | Да (сборка `tls-migration`, Linux, по запросу) | Нет (TLS-соединения отбрасываются при online restart) | Нет | +| Миграция TLS-сессии при горячей замене процесса | Да (сборка `tls-migration`, Linux, по запросу) | Нет (TLS-соединения отбрасываются при online restart) | Нет | См. [TLS](guides/tls.md). @@ -125,7 +125,7 @@ PgCat намеренно опущен: у него центр тяжести — | Возможность | PgDoorman | PgBouncer | Odyssey | | --- | :-: | :-: | :-: | -| Обновление бинаря с миграцией сессий (TCP-сокет, cancel keys, prepared cache) | Да (`SCM_RIGHTS`, плюс TLS state со сборкой `tls-migration`) | Нет: `-R` deprecated с 1.20; rolling restart через `so_reuseport` оставляет старые сессии на старом процессе | Нет: `SIGUSR2` + `bindwith_reuseport` оставляет старые сессии на старом процессе | +| Горячая замена процесса с миграцией сессий (TCP-сокет, cancel keys, prepared cache) | Да (`SCM_RIGHTS`, плюс TLS state со сборкой `tls-migration`) | Нет: `-R` deprecated с 1.20; rolling restart через `so_reuseport` оставляет старые сессии на старом процессе | Нет: `SIGUSR2` + `bindwith_reuseport` оставляет старые сессии на старом процессе | | Формат конфига | YAML или TOML | INI | Свой формат (lex/yacc) | | Человекочитаемые длительности и размеры (`30s`, `1h`, `256MB`) | Да | Нет (целые микросекунды / байты) | Нет | | Режим проверки конфига (`pg_doorman -t`) | Да | Нет | Нет | @@ -135,7 +135,7 @@ PgCat намеренно опущен: у него центр тяжести — | Лимит памяти (`max_memory_usage`) | Да | Нет | Нет | | Лимит TCP-буферов | Да (`tcp_socket_buffer_size` для клиентских TCP-сокетов и TCP-сокетов к PostgreSQL) | Да (`tcp_socket_buffer`) | Нет | -См. [Плавное обновление бинаря](tutorials/binary-upgrade.md), [Сигналы](operations/signals.md). +См. [Горячая замена процесса с переносом сессий](tutorials/binary-upgrade.md), [Сигналы](operations/signals.md). ## Протокол @@ -158,4 +158,4 @@ PgCat намеренно опущен: у него центр тяжести — - **Нужен `transaction_timeout`, который применяет сам пулер.** Используйте PgBouncer 1.25+. - **Нужен горизонтальный шардинг внутри пулера.** Используйте PgCat. -Если нужны prepared statements в transaction mode, Patroni HA без внешних прокси, многопоточная пропускная способность с одним общим пулом и обновление бинаря с миграцией живых сессий — PgDoorman ближе по профилю. +Если нужны prepared statements в transaction mode, Patroni HA без внешних прокси, многопоточная пропускная способность с одним общим пулом и горячая замена процесса с миграцией живых сессий — PgDoorman ближе по профилю. diff --git a/documentation/ru/src/guides/tls.md b/documentation/ru/src/guides/tls.md index 9a5b6fb5a..73170847f 100644 --- a/documentation/ru/src/guides/tls.md +++ b/documentation/ru/src/guides/tls.md @@ -34,7 +34,7 @@ general: Клиентские сертификаты загружаются при старте. Их смена требует рестарта процесса. Для клиентского TLS перезагрузки по `SIGHUP` нет. -Для ротации сертификатов без простоя смотрите [плавное обновление бинаря](../tutorials/binary-upgrade.md). +Горячая замена процесса может загрузить новый сертификат и ключ для новых входящих TLS-подключений, но это не бесшовная ротация для уже открытых TLS-сессий. Для переноса TLS-сессий оба процесса должны использовать те же `tls_certificate` и `tls_private_key`, а сборка должна быть Linux + `tls-migration`; при смене этих файлов TLS-клиенты дренируются и переподключаются. ### Политика шифров @@ -108,5 +108,5 @@ kill -HUP $(pidof pg_doorman) ## Куда дальше - Настройка нового кластера? Смотрите [Установку](../tutorials/installation.md). -- Ротация сертификатов? Смотрите [плавное обновление бинаря](../tutorials/binary-upgrade.md) и [Сигналы](../operations/signals.md). +- Ротация сертификатов? Смотрите [горячую замену процесса с переносом сессий](../tutorials/binary-upgrade.md) и [Сигналы](../operations/signals.md). Для переноса TLS-сессий нужна Linux-сборка с `tls-migration`. - Hardening существующего развёртывания? Сочетайте с [pg_hba.conf](../authentication/hba.md): принудительный `hostssl` для нелокальных соединений. diff --git a/documentation/ru/src/index.md b/documentation/ru/src/index.md index 05b54f441..e20911c43 100644 --- a/documentation/ru/src/index.md +++ b/documentation/ru/src/index.md @@ -6,52 +6,52 @@ ## Ключевые возможности -```admonish success title="Встроенная диагностическая консоль" -PgDoorman может отдавать веб-консоль на том же адресе и порту, что и `/metrics`. Это локальная панель для быстрой диагностики процесса и пулов, а не замена долгосрочному мониторингу в Prometheus/Grafana. +```admonish success title="Кеш анонимного Parse" +В extended protocol многие драйверы отправляют короткие параметризованные запросы как `Parse` без имени statement. PgDoorman переименовывает такой `Parse` на стороне PostgreSQL в служебный `DOORMAN_` и хранит соответствие в пуле. Следующие `Bind` для той же формы запроса используют уже подготовленное состояние. -На одном экране собраны основные сигналы для разбора инцидента: насыщение пулов, p95/p99 задержки запросов, транзакций и ожидания соединения, ошибки по SQLSTATE, долгие запросы, состояние кеша prepared statements, query interner, хвост лога, CPU по потокам tokio-worker и память процесса (`jemalloc`, `/proc/self/status`, код/библиотеки, стеки, swap). +Это снижает повторную работу планировщика PostgreSQL на горячих OLTP-запросах без изменений в приложении. PgBouncer 1.21+ и Odyssey работают с именованными prepared statements, но анонимный `Parse` передают как есть; PgDoorman закрывает этот частый сценарий у драйверов по умолчанию. -Из консоли можно выполнить Pause, Resume, Reconnect и Reload для одного пула или всего инстанса. Остальные экраны доступны только для чтения. UI включается только при `[web].ui = true` и непустом `general.admin_password`, отличном от `admin`; иначе pg_doorman оставляет только `/metrics` и пишет `WARN` в лог. +Кеш не растёт бесконтрольно: анонимные записи истекают по таймауту бездействия, именованные освобождаются после последней ссылки. `SHOW INTERNER` показывает память текстов запросов, а метрики Prometheus — попадания, промахи и вытеснения. -[Подробнее →](guides/web-ui.md) +[Подробнее →](tutorials/prepared-statements.md) ``` ```admonish success title="Координатор пулов" -PgDoorman ограничивает суммарное число серверных соединений к одной базе через `max_db_connections`. Если лимит уже выбран, координатор может освободить свободное соединение у пула с запасом и отдать слот клиенту, который ждёт соединение. +Когда несколько пользовательских пулов работают с одной базой, общий лимит должен защищать PostgreSQL, а не просто ставить клиентов в очередь. PgDoorman держит потолок через `max_db_connections`: если лимит выбран, координатор закрывает свободное соединение у пула с запасом и отдаёт слот клиенту, который ждёт подключение к PostgreSQL. + +Доноры ранжируются по излишку свободных соединений. При равном излишке первым уступает пул с более высоким p95 времени транзакции: быстрые пулы сохраняют больше шансов на переиспользование, а у медленных вытеснение свободного соединения меньше мешает работе. Резервный пул сглаживает короткие всплески, а `min_guaranteed_pool_size` защищает важные нагрузки от вытеснения. -Резервный пул сглаживает короткие всплески, а `min_guaranteed_pool_size` защищает важные нагрузки от вытеснения. В PgBouncer `max_db_connections` задаёт общий лимит, но не перераспределяет уже открытые свободные соединения между пулами; в Odyssey прямого аналога нет. +В PgBouncer `max_db_connections` задаёт общий лимит, но не перераспределяет уже открытые свободные соединения между пулами. В Odyssey прямого аналога нет. [Подробнее →](concepts/pool-coordinator.md) ``` ```admonish success title="Fallback через Patroni" -Если PgDoorman запущен рядом с PostgreSQL и локальный сервер пропадает во время Patroni switchover, пулер может временно направлять новые серверные соединения на другой живой узел кластера. Для выбора узла используется Patroni REST API (`GET /cluster`), с приоритетом `sync_standby` перед `replica`. +Если PgDoorman запущен рядом с PostgreSQL и локальный сервер пропадает во время Patroni switchover, новые серверные соединения временно уходят на другой живой узел кластера. PgDoorman выбирает узел через Patroni REST API (`GET /cluster`): сначала `sync_standby`, затем `replica`. Локальный сервер уходит в период охлаждения, а fallback-соединения получают короткий lifetime. Когда локальный узел снова доступен, пул возвращается на него без отдельного HAProxy или `consul-template` перед пулером. Настройки `patroni_api_urls` и `fallback_cooldown` задаются в `[general]`. [Подробнее →](tutorials/patroni-assisted-fallback.md) ``` -```admonish success title="Плавное обновление бинаря" -PgDoorman поддерживает переход на новый бинарь по `SIGUSR2`: новый процесс начинает принимать соединения, а старый передаёт ему свободных клиентов без повторного TCP-подключения. Это снижает всплеск `auth`/SCRAM к PostgreSQL и позволяет обновлять пулер без полной остановки трафика. +```admonish success title="Горячая замена процесса с переносом сессий" +Перед `SIGUSR2` или `UPGRADE` можно заменить бинарь и конфиг на диске. PgDoorman проверяет эту комбинацию через `-t`, запускает дочерний процесс уже с ней, передаёт ему слушающий сокет, а старый процесс продолжает обслуживать существующих клиентов и переносит мигрируемые сессии. -Свободная сессия переезжает как тот же клиентский сокет через `SCM_RIGHTS`, вместе с ключами отмены запросов и состоянием кеша prepared statements. Клиенты внутри транзакции остаются на старом процессе до завершения транзакции и мигрируют, когда снова становятся свободными. Перенос TLS-состояния OpenSSL доступен только в Linux-сборке с фичей `tls-migration`; по умолчанию она выключена. +В новый процесс уходят `connection_id`, ключ отмены запроса, параметры PostgreSQL-сессии, состояние аутентификации к PostgreSQL и клиентский кеш prepared statements. Новый процесс восстанавливает клиента в том же пуле. Для приложения соединение не рвётся: без переподключения, повторного `auth`/SCRAM и потери prepared statements. Если на новом серверном соединении statement ещё не подготовлен, PgDoorman отправит нужный `Parse` при первом `Bind`. -У PgBouncer (`-R`, устарел с 1.20, или rolling restart через `so_reuseport`) и Odyssey (`SIGUSR2` + `bindwith_reuseport`) перезапуск без остановки приёма в основном переводит новые подключения на новый процесс; старые сессии остаются на прежнем до отключения клиентов. Отличие PgDoorman здесь — перенос свободных сессий и подготовленного состояния между процессами. +В foreground-режиме TCP-сессии без TLS передаются через `SCM_RIGHTS`. TLS-сессии мигрируют только в Linux-сборке с фичей `tls-migration` и теми же `tls_certificate`/`tls_private_key`; в обычных пакетах и Docker-образе она выключена, поэтому TLS-клиенты дренируются. Клиенты внутри транзакции остаются на старом процессе и переезжают после `COMMIT` или `ROLLBACK`. У PgBouncer (`-R`, устарел с 1.20, или rolling restart через `so_reuseport`) и Odyssey (`SIGUSR2` + `bindwith_reuseport`) старые сессии остаются в старом процессе до отключения клиентов. [Подробнее →](tutorials/binary-upgrade.md) ``` -```admonish success title="Кеш Parse для анонимных prepared statements" -В extended protocol многие драйверы отправляют `Parse` с пустым именем для коротких параметризованных запросов. Без подмены такой запрос на горячем пути снова и снова платит CPU планировщика PostgreSQL и повторный `Parse` на бэкенде. +```admonish success title="Встроенная диагностическая веб-консоль" +PgDoorman отдаёт веб-консоль на том же адресе и порту, что и `/metrics`. Это локальная панель для разбора инцидента, а не замена долгосрочному мониторингу в Prometheus/Grafana. -PgDoorman назначает такому `Parse` служебное имя вида `DOORMAN_` на стороне PostgreSQL и хранит соответствие в пуле. PostgreSQL видит именованный prepared statement, а последующие `Bind` для той же формы запроса могут использовать уже подготовленное состояние. Выигрыш основной: меньше работы планировщика и меньше повторных `Parse` на бэкенде для повторяющихся OLTP-запросов. Приложению не нужно переводить драйвер на явные имена statement. +На одном экране видны насыщение пулов, p95/p99 задержки запросов, транзакций и ожидания соединения, ошибки по SQLSTATE, долгие запросы, состояние prepared statements и query interner, хвост лога, CPU по потокам `tokio-worker` и память процесса (`jemalloc`, `/proc/self/status`, код/библиотеки, стеки, swap). -PgBouncer 1.21+ и Odyssey умеют работать с именованными prepared statements в transaction mode. PgDoorman дополнительно обрабатывает безымянные prepared statements, которые часто встречаются у драйверов по умолчанию. +Из консоли можно выполнить Pause, Resume, Reconnect и Reload для одного пула или всего инстанса. Остальные экраны доступны только для чтения. Веб-интерфейс включается только при `[web].ui = true` и непустом `general.admin_password`, отличном от `admin`; иначе PgDoorman оставляет только `/metrics` и пишет `WARN` в лог. -Чтобы оптимизация производительности не превращалась в неконтролируемую память, кеш имеет ограничения и жизненный цикл. Анонимные записи истекают по таймауту бездействия, именованные освобождаются, когда на них больше нет ссылок. `SHOW INTERNER` показывает память текстов запросов, а метрики Prometheus — попадания, промахи и вытеснения. - -[Подробнее →](tutorials/prepared-statements.md) +[Подробнее →](guides/web-ui.md) ``` ## Почему PgDoorman @@ -74,7 +74,7 @@ PgBouncer 1.21+ и Odyssey умеют работать с именованным | Переключение на резервный узел через Patroni | Да, встроено | Нет | Нет | | Опережающая замена стареющих серверных соединений | Да | Нет | Нет | | Обрыв серверного соединения во время транзакции | Да, возвращает `08006` без ожидания TCP keepalive | Нет, ждёт TCP keepalive | Нет, ждёт TCP keepalive | -| Обновление бинаря с переносом свободных сессий | Да, через `SCM_RIGHTS`; TLS-состояние при сборке `tls-migration` | Нет, старые сессии остаются в старом процессе | Нет, старые сессии остаются в старом процессе | +| Горячая замена процесса с переносом свободных сессий | Да, через `SCM_RIGHTS`; TLS-состояние при сборке `tls-migration` | Нет, старые сессии остаются в старом процессе | Нет, старые сессии остаются в старом процессе | | TLS-соединение от пулера к PostgreSQL | Да, 5 режимов и reload по `SIGHUP` | Да, `server_tls_*` и reload по `RELOAD` | Нет | | SCRAM passthrough без открытого пароля в конфиге | Да, извлекает `ClientKey` из `SCRAM proof` | Да, зашифрованный SCRAM secret через `auth_query`/`userlist.txt`, с 1.14 | Да | | JWT-аутентификация (RSA-SHA256) | Да | Нет | Нет | @@ -159,4 +159,4 @@ pools: - Мигрируете с PgBouncer или Odyssey? Прочитайте [Сравнение](comparison.md) и [Аутентификацию](authentication/overview.md). - Используете Patroni? См. [Fallback через Patroni](tutorials/patroni-assisted-fallback.md) и [`patroni_proxy`](tutorials/patroni-proxy.md). - Готовитесь к промышленной эксплуатации? Прочитайте [Пул под нагрузкой](tutorials/pool-pressure.md) и [Координатор пулов](concepts/pool-coordinator.md). -- Эксплуатируете PgDoorman? См. [Обновление бинаря](tutorials/binary-upgrade.md), [Сигналы](operations/signals.md), [Диагностику проблем](tutorials/troubleshooting.md). +- Эксплуатируете PgDoorman? См. [Горячую замену процесса](tutorials/binary-upgrade.md), [Сигналы](operations/signals.md), [Диагностику проблем](tutorials/troubleshooting.md). diff --git a/documentation/ru/src/operations/signals.md b/documentation/ru/src/operations/signals.md index d10f6e675..6cdeaa747 100644 --- a/documentation/ru/src/operations/signals.md +++ b/documentation/ru/src/operations/signals.md @@ -8,7 +8,7 @@ pg_doorman реагирует на четыре POSIX-сигнала: `SIGHUP`, | --- | --- | --- | --- | | `SIGHUP` | Перезагрузить конфиг с диска. | Сохраняются. | Подкрутить пулы, ротировать серверные TLS-сертификаты, отредактировать `pg_hba.conf`. | | `SIGTERM` | Немедленное завершение. | Закрываются. | Остановка сервиса, когда переподключения допустимы. | -| `SIGUSR2` | Обновление бинарника и дренирование старого процесса. | Мигрируют в новый процесс, где это возможно. | Замена бинарника без простоя. | +| `SIGUSR2` | Горячая замена процесса: новый бинарь и конфиг, затем дренирование старого процесса. | Мигрируют в новый процесс, где это возможно; TLS требует `tls-migration`. | Раскатить изменения, которым нужен новый процесс. | | `SIGINT` | Зависит от TTY (см. ниже). | По-разному. | Ctrl+C при разработке; устарело для промышленной эксплуатации. | ## Перезагрузка (`SIGHUP`) @@ -33,7 +33,7 @@ kill -HUP $(pidof pg_doorman) значение применяется только при приёме нового клиентского TCP-сокета или открытии нового TCP-сокета к PostgreSQL. - TLS-сертификаты для входящих клиентских подключений — нужен перезапуск - процесса. Не ротируйте их во время обновления, где нужна миграция + процесса. Не ротируйте их во время горячей замены, где нужна миграция TLS-сессий. - Число рабочих потоков и параметры рантайма Tokio. @@ -49,45 +49,45 @@ pg_doorman логирует, сколько клиентов ещё в тран не ждёт `shutdown_timeout` и не мигрирует активные транзакции. Все клиентские соединения закрываются при выходе процесса. -`shutdown_timeout` относится к дренированию при обновлении бинарника +`shutdown_timeout` относится к дренированию при горячей замене процесса через `SIGUSR2`, а не к обычному завершению по `SIGTERM`. -## Обновление бинарника (`SIGUSR2`) +## Горячая замена процесса (`SIGUSR2`) ```bash kill -USR2 $(pidof pg_doorman) ``` -Рекомендуемый способ заменить бинарник, не теряя клиентов: +Рекомендуемый способ заменить процесс, не теряя мигрируемых клиентов: -1. Замените бинарник на диске новой версией через атомарный `rename`. +1. Замените бинарник и/или конфиг на диске. 2. Отправьте `SIGUSR2` работающему процессу. -3. Текущий процесс проверяет новый бинарник через `-t`. -4. Текущий процесс порождает дочерний с новым бинарником, передаёт ему слушающий сокет и продолжает обслуживать существующих клиентов до их завершения. +3. Текущий процесс проверяет новый бинарник с конфигом через `-t`. +4. Текущий процесс порождает дочерний процесс с теми же аргументами запуска, передаёт ему слушающий сокет и продолжает обслуживать существующих клиентов до миграции или завершения. 5. Новые клиенты сразу подключаются к дочернему процессу. -6. Старый процесс выходит, когда последняя клиентская транзакция завершится (или по `shutdown_timeout`). +6. Старый процесс выходит, когда клиенты мигрировали или отключились (или по `shutdown_timeout`). Дочерний процесс отправляет `sd_notify MAINPID=`, чтобы юниты systemd с `Type=notify` корректно отслеживали новый главный PID. -Если при обновлении изменён `general.tcp_socket_buffer_size`, новый +Если при горячей замене изменён `general.tcp_socket_buffer_size`, новый процесс применяет его к мигрировавшим клиентским TCP-сокетам при восстановлении клиента. Backend-сокеты через `SCM_RIGHTS` не передаются: новые backend-соединения получают настройку при открытии, а старые остаются в старом процессе до дренирования. -Полный протокол, миграцию TLS и откат смотрите в [обновлении бинарника без переподключения](../tutorials/binary-upgrade.md). +Полный протокол, миграцию TLS и откат смотрите в [горячей замене процесса с переносом сессий](../tutorials/binary-upgrade.md). ## `SIGINT` (Ctrl+C) `SIGINT` зависит от контекста: - **На переднем плане с TTY** (разработка, `cargo run`): только завершение работы. -- **В режиме демона или без TTY**: запускает обновление бинарника и +- **В режиме демона или без TTY**: запускает горячую замену процесса и дренирование старого процесса, как `SIGUSR2`, для совместимости со старыми установками. -Путь обновления через `SIGINT` существует ради обратной совместимости с инсталляциями, которые отправляют `SIGINT` из init-скриптов. Новые инсталляции должны явно использовать `SIGUSR2` для обновления и `SIGTERM` для остановки. +Путь горячей замены через `SIGINT` существует ради обратной совместимости с инсталляциями, которые отправляют `SIGINT` из init-скриптов. Новые инсталляции должны явно использовать `SIGUSR2` для горячей замены и `SIGTERM` для остановки. ## Интеграция с systemd @@ -110,10 +110,10 @@ Group=postgres LimitNOFILE=65536 ``` -`sd_notify READY=1` отправляется после привязки слушающего сокета и инициализации пулов. `sd_notify MAINPID=` отправляется при обновлении бинарника, чтобы systemd корректно отслеживал новый процесс. +`sd_notify READY=1` отправляется после привязки слушающего сокета и инициализации пулов. `sd_notify MAINPID=` отправляется при горячей замене процесса, чтобы systemd корректно отслеживал новый процесс. -С таким юнитом `systemctl reload pg_doorman` означает обновление -бинарника (`SIGUSR2`), а не перечитывание конфига (`SIGHUP`). Если нужно +С таким юнитом `systemctl reload pg_doorman` означает горячую замену +процесса (`SIGUSR2`), а не перечитывание конфига (`SIGHUP`). Если нужно только перечитать конфиг, используйте `kill -HUP `. Если переходите с `Type=forking` + `--daemon`, уберите `--daemon` и переключитесь на `Type=notify` — меньше движущихся частей и корректное отслеживание готовности. Старые инсталляции с `--daemon` продолжают работать, но не получают преимуществ `sd_notify`. @@ -129,6 +129,6 @@ general: ## Куда дальше -- [Обновление бинарника без переподключения](../tutorials/binary-upgrade.md) — полный протокол обновления с миграцией TLS. +- [Горячая замена процесса с переносом сессий](../tutorials/binary-upgrade.md) — полный протокол замены с миграцией TLS. - [Диагностика](../tutorials/troubleshooting.md) — что проверить, когда перезагрузка не подхватывает изменения. - [TLS](../guides/tls.md) — семантика перезагрузки серверных сертификатов по `SIGHUP`. diff --git a/documentation/ru/src/reference/general.md b/documentation/ru/src/reference/general.md index b615699ae..cc05afa01 100644 --- a/documentation/ru/src/reference/general.md +++ b/documentation/ru/src/reference/general.md @@ -464,7 +464,7 @@ TCP retransmission timeout, когда keepalive не помогает (напр Этот параметр в первую очередь ограничивает память. Стартовый диапазон для OLTP внутри одного датацентра: **64 KiB – 256 KiB**. Не ставьте меньше 64 KiB без замеров. Для WAN, межзонального трафика, больших результатов запроса и массовой передачи данных может понадобиться большее значение или поведение по умолчанию с автонастройкой TCP. -Значение применяется, когда pg_doorman настраивает TCP-сокет: к новым клиентским подключениям, новым TCP-соединениям к PostgreSQL и клиентским сокетам, восстановленным в новом процессе через `SCM_RIGHTS`. `SIGHUP` не пересматривает уже открытые сокеты. Чтобы применить новое значение к существующим сессиям, используйте binary upgrade для мигрирующих клиентов, `RECONNECT`/дренирование пулов для backend-сокетов или обычный рестарт, если переподключения допустимы. +Значение применяется, когда pg_doorman настраивает TCP-сокет: к новым клиентским подключениям, новым TCP-соединениям к PostgreSQL и клиентским сокетам, восстановленным в новом процессе через `SCM_RIGHTS`. `SIGHUP` не пересматривает уже открытые сокеты. Чтобы применить новое значение к существующим сессиям, используйте горячую замену процесса для мигрирующих клиентов, `RECONNECT`/дренирование пулов для backend-сокетов или обычный рестарт, если переподключения допустимы. Это аналог параметра `tcp_socket_buffer` в PgBouncer. В Odyssey и PgCat аналога нет, они наследуют поведение автонастройки TCP в Linux. diff --git a/documentation/ru/src/tutorials/basic-usage.md b/documentation/ru/src/tutorials/basic-usage.md index 88e6b8759..cfe05b875 100644 --- a/documentation/ru/src/tutorials/basic-usage.md +++ b/documentation/ru/src/tutorials/basic-usage.md @@ -627,10 +627,10 @@ PgDoorman реагирует на стандартные Unix-сигналы д | Сигнал | Эффект | |--------|--------| | **SIGHUP** | Перечитывание конфигурации — эквивалент admin-команды `RELOAD`. | -| **SIGUSR2** | Обновление бинаря и плавное завершение старого процесса. Валидирует новый бинарник флагом `-t`, запускает новый процесс, затем завершается. **Рекомендуется для обновлений.** См. [Плавное обновление бинаря](binary-upgrade.md). | -| **SIGINT** | **Foreground + TTY** (Ctrl+C): только плавное завершение (без обновления бинаря). **Режим демона / без TTY**: обновление бинаря и плавное завершение для совместимости со старыми установками. | +| **SIGUSR2** | Горячая замена процесса. Валидирует новый бинарь и конфиг флагом `-t`, запускает новый процесс, передаёт ему слушающий сокет и переносит сессии, где это возможно. **Рекомендуется для обновлений.** См. [Горячая замена процесса с переносом сессий](binary-upgrade.md). | +| **SIGINT** | **Foreground + TTY** (Ctrl+C): только плавное завершение (без замены процесса). **Режим демона / без TTY**: горячая замена процесса для совместимости со старыми установками. | | **SIGTERM** | Немедленное завершение. Активные соединения обрываются. | ```admonish note title="Управление процессом" -В окружениях на базе systemd unit-файл по умолчанию использует `ExecReload=/bin/kill -SIGUSR2 $MAINPID`, чтобы запускать binary upgrade при `systemctl reload`. +В окружениях на базе systemd unit-файл по умолчанию использует `ExecReload=/bin/kill -SIGUSR2 $MAINPID`, чтобы запускать горячую замену процесса при `systemctl reload`. ``` diff --git a/documentation/ru/src/tutorials/binary-upgrade.md b/documentation/ru/src/tutorials/binary-upgrade.md index 97a8350fb..474085acb 100644 --- a/documentation/ru/src/tutorials/binary-upgrade.md +++ b/documentation/ru/src/tutorials/binary-upgrade.md @@ -1,14 +1,23 @@ -# Обновление бинарника без переподключения +# Горячая замена процесса с переносом сессий -pg_doorman умеет заменить исполняемый файл на работающем сервере по -`SIGUSR2`. Свободные клиенты передаются новому процессу через -Unix-сокет вместе с ключами отмены запросов и кешем prepared statements. -Клиент остаётся на том же TCP-соединении и не проходит повторное -подключение. +Перед `SIGUSR2` или admin-командой `UPGRADE` можно заменить бинарь и +конфиг на диске. Работающий процесс проверит эту комбинацию через `-t`, +запустит дочерний процесс с теми же аргументами запуска, передаст ему +слушающий сокет и переведёт на него новые подключения. + +Старый процесс продолжает обслуживать уже подключённых клиентов и +переносит свободные TCP-сессии без TLS в новый процесс через Unix-сокет. +Клиент остаётся на том же TCP-соединении: вместе с файловым +дескриптором передаются ключ отмены запроса, параметры +PostgreSQL-сессии и кеш prepared statements. Клиенты внутри транзакции продолжают работать на старом процессе и переезжают, когда транзакция завершится. Для приложений это убирает -волну переподключений, а для PostgreSQL — всплеск SCRAM-аутентификаций. +волну переподключений, а для PostgreSQL — всплеск `auth`/SCRAM. + +TLS-сессии мигрируют только в Linux-сборке с фичей `tls-migration`. +Дистрибутивные пакеты и Docker-образ собраны без неё, поэтому TLS-клиенты +при такой замене дренируются и переподключаются к новому процессу. ```admonish info title="Чем это отличается от PgBouncer / Odyssey" PgBouncer (`-R`, устарел с 1.20, или rolling restart через @@ -32,18 +41,19 @@ Linux-сборке с `tls-migration` может перенести и сост ``` ```bash -# 1. Установите новый бинарник по пути, из которого запущен сервис. +# 1. Установите новый бинарник по пути, из которого запущен сервис, +# и при необходимости обновите конфиг на диске. install -m 0755 pg_doorman_new /usr/bin/pg_doorman -# 2. Проверьте, что новый бинарник принимает текущий конфиг, до того -# как запускать обновление. SIGUSR2 тоже прогоняет `-t` и отменяет -# обновление при ошибке, но проверка здесь даёт шанс починить конфиг, +# 2. Проверьте, что новый процесс стартует с этим конфигом, до того +# как запускать замену. SIGUSR2 тоже прогоняет `-t` и отменяет +# замену при ошибке, но проверка здесь даёт шанс починить конфиг, # не трогая работающий сервер. /usr/bin/pg_doorman -t /etc/pg_doorman/pg_doorman.toml -# 3. Запустите обновление. С `ExecReload=/bin/kill -SIGUSR2 $MAINPID` +# 3. Запустите замену процесса. С `ExecReload=/bin/kill -SIGUSR2 $MAINPID` # в юните `systemctl reload` отправляет SIGUSR2 и запускает -# обновление бинарника. Дальше pg_doorman проверяет конфиг, +# горячую замену процесса. Дальше pg_doorman проверяет конфиг, # запускает дочерний процесс, мигрирует состояние где возможно и # дренирует старый процесс. systemd шлёт сигнал в MainPID, поэтому # выбирается ровно один процесс, даже если на хосте есть @@ -74,7 +84,7 @@ psql -h pgdoorman -p 6432 -c 'SHOW POOLS;' # отвечает новый про процесса-супервизора и шлите сигнал ему напрямую. ``` -То же обновление можно запустить из консоли администратора: +Ту же замену процесса можно запустить из консоли администратора: ```sql UPGRADE; @@ -84,7 +94,7 @@ UPGRADE; `kill -USR2`. Успешный ответ команды означает, что сигнал отправлен, а не что проверка и миграция уже закончились. -## Как работает обновление +## Как работает замена ``` SIGUSR2 @@ -126,10 +136,11 @@ UPGRADE; ### Фаза 1: Проверка конфига Работающий процесс берёт путь, из которого стартовал сам, и запускает -его с `-t` и текущим конфигом. После `install` из быстрого старта этот -путь уже указывает на новый бинарник, поэтому проверяется именно тот -процесс, который должен принять трафик. Если проверка проваливается, -обновление отменяется, а старый процесс продолжает обслуживать трафик. +его с `-t` и текущим конфигом. После `install` и правки конфига из +быстрого старта этот путь уже указывает на новый бинарник и новый файл +конфига, поэтому проверяется именно процесс, который должен принять +трафик. Если проверка проваливается, +замена отменяется, а старый процесс продолжает обслуживать трафик. В логах появляется баннер: ``` @@ -232,7 +243,7 @@ UPGRADE; По умолчанию TLS-клиенты не мигрируют — зашифрованная сессия требует ключевой материал, который живёт внутри автомата OpenSSL. -Такие клиенты дренируются при обновлении: соединение закрывается при +Такие клиенты дренируются при замене процесса: соединение закрывается при истечении `shutdown_timeout`, клиент переподключается к новому процессу. Опциональная сборка с `tls-migration` решает эту проблему. Патченный @@ -342,17 +353,17 @@ SHA-256 архива проверяется автоматически. | Сигнал | Поведение | |--------|-----------| -| `SIGUSR2` | Обновление бинарника + дренирование старого процесса. **Рекомендуемый для всех режимов.** | -| `SIGINT` | В foreground + TTY (Ctrl+C): только завершение, без обновления. В режиме демона или без TTY: обновление бинарника для совместимости со старыми установками. | +| `SIGUSR2` | Горячая замена процесса + дренирование старого процесса. **Рекомендуемый для всех режимов.** | +| `SIGINT` | В foreground + TTY (Ctrl+C): только завершение, без замены процесса. В режиме демона или без TTY: горячая замена процесса для совместимости со старыми установками. | | `SIGTERM` | Немедленный выход. Транзакции обрываются. Все клиенты отключаются. | | `SIGHUP` | Перечитать конфигурацию без перезапуска. Без простоя. | | `UPGRADE` (admin) | Отправляет SIGUSR2 текущему процессу. Тот же эффект. | > **Поведение `SIGINT` для совместимости:** -> `SIGINT` запускает обновление бинарника в режиме демона или без TTY +> `SIGINT` запускает горячую замену процесса в режиме демона или без TTY > (например, под systemd). В интерактивном терминале Ctrl+C останавливает > процесс без запуска нового. Используйте `kill -USR2` или `UPGRADE` в -> консоли администратора для обновления в foreground-режиме. +> консоли администратора для горячей замены в foreground-режиме. ## Режим демона и foreground-режим @@ -361,10 +372,10 @@ SHA-256 архива проверяется автоматически. | Миграция клиентов через передачу fd | Да (`socketpair`) | Нет | | Свободные клиенты сохраняются | Да | Нет (закрываются при выходе старого процесса) | | Клиенты внутри транзакции | Завершают транзакцию, затем мигрируют | Работают до таймаута, затем закрываются | -| Запуск нового процесса | Наследует файловый дескриптор listener | Запускается независимо | +| Запуск нового процесса | Наследует файловый дескриптор слушающего сокета | Запускается независимо | | Рекомендуется для | systemd, контейнеры, Kubernetes | Старые установки | -Для обновления без простоя и с миграцией клиентов запускайте pg_doorman +Для горячей замены процесса с миграцией клиентов запускайте pg_doorman в foreground-режиме. systemd управляет жизненным циклом процесса. Используйте `Type=notify`: юнит становится `active` только после сигнала готовности от pg_doorman, а новый процесс при `SIGUSR2` @@ -377,20 +388,20 @@ Type=notify # отправить READY=1 и MAINPID= во время передачи управления. NotifyAccess=exec ExecStart=/usr/bin/pg_doorman /etc/pg_doorman/pg_doorman.toml -# `systemctl reload` запускает обновление бинарника: проверка конфига, +# `systemctl reload` запускает горячую замену процесса: проверка конфига, # новый процесс, миграция клиентов где возможно, затем дренирование # старого процесса по shutdown_timeout из конфига pg_doorman. ExecReload=/bin/kill -SIGUSR2 $MAINPID -# `systemctl stop` — немедленное завершение. Это не путь обновления, +# `systemctl stop` — немедленное завершение. Это не путь горячей замены, # и он не ждёт миграции активных транзакций. ExecStop=/bin/kill -SIGTERM $MAINPID -# При обновлении новый дочерний процесс становится MainPID через sd_notify. +# При горячей замене новый дочерний процесс становится MainPID через sd_notify. # KillMode=mixed при обычном stop шлёт SIGTERM только в MainPID, а # оставшиеся процессы cgroup добивает SIGKILL только после TimeoutStopSec. KillMode=mixed TimeoutStopSec=60 # Не перезапускать сервис после чистой ручной остановки или после выхода -# старого процесса, который успешно передал трафик новому при обновлении. +# старого процесса, который успешно передал трафик новому при замене. Restart=on-failure Nice=-15 # pg_doorman активно использует дескрипторы: каждый клиент и каждый @@ -408,7 +419,7 @@ SyslogIdentifier=pg_doorman `systemctl reload pg_doorman` отправляет `SIGUSR2`; нулевой код выхода означает только, что сигнал доставлен. Затем pg_doorman прогоняет `-t` -на новом бинарнике, отменяет обновление при битом конфиге, иначе +на новом бинарнике, отменяет замену при битом конфиге, иначе порождает новый процесс и дренирует старый. `UPGRADE;` из админ-консоли идёт по тому же пути. Окно дренирования задаёт `shutdown_timeout` в `pg_doorman.toml`; `TimeoutStopSec` относится к обычному @@ -417,7 +428,7 @@ SyslogIdentifier=pg_doorman Продакшен-установки часто добавляют сверху ограничения ресурсов: `MemoryMax=`, `CPUAffinity=2,3,4,5,6,7,8,9`. Это зависит от нагрузки -и не меняет контракт обновления. +и не меняет контракт горячей замены. ## Конфигурация @@ -453,11 +464,11 @@ shutdown_timeout = 60000 # миллисекунды Клиентский TLS-материал **не** перезагружается по `SIGHUP` (это делает только серверный TLS, см. [горячую перезагрузку TLS](../guides/tls.md)). Не совмещайте ротацию сертификата для входящих клиентских TLS-соединений -с обновлением, где вы ожидаете миграцию TLS-сессий. Если файлы +с горячей заменой, где вы ожидаете миграцию TLS-сессий. Если файлы отличаются между старым и новым процессом, импорт TLS-состояния падает, и затронутые клиенты переподключаются даже с включённым `tls-migration`. Ротируйте этот сертификат в окно, где переподключения -допустимы, либо оставьте те же файлы на время обновления бинарника и +допустимы, либо оставьте те же файлы на время горячей замены процесса и меняйте сертификат позже через рестарт. ### `prepared_statements_cache_size` @@ -475,11 +486,11 @@ LRU-кеш анонимных записей на клиента. Клиентс ## Откат -У обновления бинарника нет отдельного пути отмены. Для отката положите -предыдущий бинарник на тот же путь и запустите ещё одно обновление через +У горячей замены процесса нет отдельного пути отмены. Для отката положите +предыдущий бинарник на тот же путь и запустите ещё одну замену через `SIGUSR2`. Если проверка конфига провалится, текущий процесс продолжит обслуживать трафик. Если новый процесс уже принял трафик, откат -проходит как обычное обновление в обратную сторону. +проходит как обычная горячая замена в обратную сторону. Не используйте `systemctl restart` или `SIGTERM` для отката, если переподключения недопустимы: оба пути закрывают клиентские сессии, а не @@ -515,7 +526,7 @@ INFO migration receiver: stopped ### Prometheus-метрики -| Метрика | Значение при обновлении | +| Метрика | Значение при замене процесса | |---------|----------------------| | `pg_doorman_pools_clients{status="active"}` | Должна упасть до 0 на старом процессе | | `pg_doorman_pools_clients{status="idle"}` | Падает по мере миграции клиентов | @@ -535,7 +546,7 @@ SHOW CLIENTS; ### Клиент получил 58006 или отключился вместо миграции **Ctrl+C в foreground-режиме.** `SIGINT` в TTY означает завершение без -обновления. Используйте `kill -USR2` или `UPGRADE` в консоли +горячей замены. Используйте `kill -USR2` или `UPGRADE` в консоли администратора. **Режим демона.** В режиме демона нет миграции через файловые @@ -557,7 +568,7 @@ SHOW CLIENTS; **Принудительный выход:** `kill -TERM ` отправляет `SIGTERM` и завершает процесс без ожидания миграции. -### TLS-соединение оборвалось после обновления +### TLS-соединение оборвалось после замены процесса **Бинарник собран без `--features tls-migration`.** TLS-клиенты дренируются вместо миграции. Пересоберите с `--features tls-migration`. @@ -602,20 +613,20 @@ TLS-соединений. Если нужна миграция TLS-сессий, ## Чек-лист перед продакшеном -Перед выкатом обновления бинарника: +Перед выкатом горячей замены процесса: - [ ] Запуск в **foreground-режиме** (не `daemon`) для миграции через файловые дескрипторы - [ ] `shutdown_timeout` покрывает самую длинную ожидаемую транзакцию (рекомендация: 30–60 секунд для OLTP, больше для аналитики) - [ ] Если используете TLS: сборка с `--features tls-migration`, оба процесса используют одинаковые файлы сертификата и ключа -- [ ] Протестировать обновление на staging: открыть сессию, отправить +- [ ] Протестировать замену на staging: открыть сессию, отправить SIGUSR2, убедиться что сессия продолжает работать - [ ] В systemd-юните указано `Type=notify` с `NotifyAccess=exec`, `ExecReload=/bin/kill -SIGUSR2 $MAINPID` (тогда `systemctl - reload` запускает обновление бинарника с проверкой конфига), + reload` запускает горячую замену процесса с проверкой конфига), `KillMode=mixed` и `Restart=on-failure` -- [ ] Мониторинг логов на ошибки миграции после первого обновления в +- [ ] Мониторинг логов на ошибки миграции после первой замены в продакшене - [ ] Подтвердить что старый процесс завершился (PID-файл или `pgrep`) - [ ] Проверить Prometheus-метрики: клиенты на новом процессе diff --git a/documentation/ru/src/tutorials/installation.md b/documentation/ru/src/tutorials/installation.md index d017678e9..4f92210e9 100644 --- a/documentation/ru/src/tutorials/installation.md +++ b/documentation/ru/src/tutorials/installation.md @@ -26,12 +26,12 @@ sudo install -m 0755 target/release/pg_doorman /usr/local/bin/pg_doorman | Фича | По умолчанию | Эффект | | --- | --- | --- | -| `tls-migration` | выкл | Vendored OpenSSL 3.5.5 с патчем, позволяющим TLS-клиентам пережить обновление бинарника. **Нужен для обновления TLS-клиентов без простоя.** | +| `tls-migration` | выкл | Vendored OpenSSL 3.5.5 с патчем, позволяющим переносить TLS-клиентов при горячей замене процесса. **Нужен, если TLS-клиенты должны мигрировать без переподключения.** | | `pam` | выкл | Поддержка аутентификации PAM (Linux). | ### Сборка с миграцией TLS-клиентов -По умолчанию TLS-клиенты не могут перейти на новый процесс при обновлении бинарника — они получают ошибку `58006` и переподключаются. Чтобы соединения переходили на новый процесс без разрыва, соберите с фичей `tls-migration`: +По умолчанию TLS-клиенты не могут перейти на новый процесс при горячей замене процесса — они получают ошибку `58006` и переподключаются. Чтобы TLS-соединения переходили на новый процесс без разрыва, соберите с фичей `tls-migration`: ```bash cargo build --release --features tls-migration @@ -118,9 +118,9 @@ docker run -p 6432:6432 \ Пробрасывайте `6432` для PostgreSQL-протокола. Если в конфиге включён `web.enabled`, дополнительно пробросьте `9127` для `/metrics` и веб-консоли; без этого флага listener не поднимается. Путь к конфигу можно задать позиционным аргументом или переменной `CONFIG_FILE`; также доступны `LOG_LEVEL` (по умолчанию `info`), `LOG_FORMAT` (`text`, `structured` или `debug`) и `NO_COLOR`. -В Dockerfile задан `STOPSIGNAL SIGTERM`, поэтому `docker stop` отправляет `pg_doorman` обычный сигнал остановки контейнера. Не используйте `SIGINT` для остановки контейнера: вне TTY этот сигнал запускает binary upgrade, что для контейнерного запуска обычно приводит к завершению PID 1. +В Dockerfile задан `STOPSIGNAL SIGTERM`, поэтому `docker stop` отправляет `pg_doorman` обычный сигнал остановки контейнера. Не используйте `SIGINT` для остановки контейнера: вне TTY этот сигнал запускает горячую замену процесса, что для контейнерного запуска обычно приводит к завершению PID 1. -Публичный образ собран без фич `tls-migration` и `pam`. Обычный TLS для клиентских и серверных соединений не зависит от `tls-migration`; эта фича нужна только для переноса TLS-сессий при обновлении бинарника. Для TLS migration или PAM соберите свой образ из публичного `Dockerfile`, добавив `--features tls-migration` и/или `pam` в шаг `cargo build --release`. +Публичный образ собран без фич `tls-migration` и `pam`. Обычный TLS для клиентских и серверных соединений не зависит от `tls-migration`; эта фича нужна только для переноса TLS-сессий при горячей замене процесса. Для TLS migration или PAM соберите свой образ из публичного `Dockerfile`, добавив `--features tls-migration` и/или `pam` в шаг `cargo build --release`. `docker-compose.yaml` с PostgreSQL в качестве sidecar лежит в [`example/`](https://github.com/ozontech/pg_doorman/tree/master/example) — для smoke-тестов. @@ -139,4 +139,4 @@ psql -h 127.0.0.1 -p 6432 -U admin pgdoorman -c "SHOW VERSION;" - [Базовое использование](./basic-usage.md) — первый конфиг, admin-консоль, мониторинг. - [Аутентификация](../authentication/overview.md) — выбор подходящего метода. - [Сигналы и перезагрузка](../operations/signals.md) — сигналы, reload, интеграция с systemd. -- [Плавное обновление бинаря](./binary-upgrade.md) — замена бинарника без потери клиентов. +- [Горячая замена процесса с переносом сессий](./binary-upgrade.md) — новый бинарь и конфиг с переносом мигрируемых клиентов. diff --git a/documentation/ru/src/tutorials/overview.md b/documentation/ru/src/tutorials/overview.md index d0eee178c..5a7863545 100644 --- a/documentation/ru/src/tutorials/overview.md +++ b/documentation/ru/src/tutorials/overview.md @@ -12,7 +12,7 @@ graph LR Pooler --> DB[(PostgreSQL)] ``` -Изначально PgDoorman был форкнут из [PgCat](https://github.com/postgresml/pgcat), но с тех пор переписан вокруг других целей: prepared statements в transaction mode, многопоточные общие пулы, интеграция с Patroni и обновление бинаря с миграцией живых сессий. Сейчас это самостоятельная кодовая база. +Изначально PgDoorman был форкнут из [PgCat](https://github.com/postgresml/pgcat), но с тех пор переписан вокруг других целей: prepared statements в transaction mode, многопоточные общие пулы, интеграция с Patroni и горячая замена процесса с миграцией живых сессий. Сейчас это самостоятельная кодовая база. ## Зачем вообще пулер @@ -51,4 +51,4 @@ PgDoorman не реализует statement mode. См. [режимы пула]( - [Установка](installation.md) — установить pg_doorman из пакетов, исходников или Docker. - [Базовое использование](basic-usage.md) — минимальный конфиг, первое подключение, типичные грабли. - [Координатор пулов](../concepts/pool-coordinator.md) — когда одна база делится между несколькими пользовательскими пулами. -- [Плавное обновление бинаря](binary-upgrade.md) — заменить бинарник в промышленной эксплуатации без потери живых сессий. +- [Горячая замена процесса с переносом сессий](binary-upgrade.md) — заменить процесс в промышленной эксплуатации и перенести мигрируемые сессии. diff --git a/documentation/ru/src/tutorials/troubleshooting.md b/documentation/ru/src/tutorials/troubleshooting.md index 8d90e33b4..3f8aaf29c 100644 --- a/documentation/ru/src/tutorials/troubleshooting.md +++ b/documentation/ru/src/tutorials/troubleshooting.md @@ -53,9 +53,9 @@ pg_doorman -t /etc/pg_doorman/pg_doorman.yaml ## Клиенты получают `58006` (`pooler is shut down now`) -Пул выключается, либо обновление бинаря было запущено в режиме демона. Посмотрите серверные логи рядом с временем ошибки: +Пул выключается, либо горячая замена процесса была запущена в режиме демона. Посмотрите серверные логи рядом с временем ошибки: -- `Got SIGUSR2, starting binary upgrade …` — идёт обновление бинаря. В foreground-режиме свободные клиенты должны мигрировать прозрачно; `58006` получают только клиенты, оставшиеся в транзакции после `shutdown_timeout`. В режиме демона миграции через файловые дескрипторы нет, и каждый клиент получает `58006` при закрытии соединения. См. [Плавное обновление бинаря → Диагностика](binary-upgrade.md#Диагностика). +- `Got SIGUSR2, starting binary upgrade …` — идёт горячая замена процесса. В foreground-режиме свободные TCP-клиенты без TLS должны мигрировать прозрачно; TLS-клиенты мигрируют только со сборкой `tls-migration`. `58006` получают клиенты, оставшиеся в транзакции после `shutdown_timeout`. В режиме демона миграции через файловые дескрипторы нет, и каждый клиент получает `58006` при закрытии соединения. См. [Горячая замена процесса с переносом сессий → Диагностика](binary-upgrade.md#Диагностика). - Нет строки `SIGUSR2` в логе — кто-то прислал `SIGTERM` или `SIGINT`, и пулер выключился без замены. Проверьте systemd-юнит, конкретный pid и operator runbook. Если `58006` пришёл во время плановой замены — для этой подмножества клиентов это ожидаемое поведение. Настройте connection pool приложения на retry при transient-ошибках.