Pool Coordinator
Pool Coordinator ограничивает суммарное число backend-соединений к одной базе по всем пользователям пула, а при достижении лимита применяет приоритетное вытеснение. Это то, чем должен был стать max_db_connections в PgBouncer: справедливое применение лимита, резерв на короткие всплески и минимум на пользователя, защищающий критичные нагрузки.
Эта страница объясняет концепцию и сценарии применения. Рецепты тюнинга и разбор вывода SHOW POOL_COORDINATOR смотрите в Пул под нагрузкой.
Какую задачу решает
Без координатора каждый user-пул независим. pool_size равный 40 у пяти пользователей означает до 200 backend-соединений — и PostgreSQL приходится бороться за свои собственные лимиты.
max_db_connections в PgBouncer ограничивает общую сумму, но блокирует новые запросы, как только лимит достигнут. Кто первым занял слоты, тот и удерживает их независимо от интенсивности использования, а медленные нагрузки никогда не уступают быстрым.
Pool Coordinator в pg_doorman ограничивает сумму и:
- Вытесняет idle-соединения у пользователей с переизбытком, когда другому пользователю нужно вырасти.
- Ранжирует пользователей по p95 времени транзакции, чтобы медленные пулы отдавали слоты первыми. Пользователи с быстрыми запросами сохраняют преимущество переиспользования; пользователи с длинными транзакциями отдают первыми, потому что их соединения и так дольше простаивали.
- Резервирует небольшое переполнение для коротких всплесков. Настраивается отдельно от основного лимита.
- Гарантирует минимум на пользователя, который никогда не вытесняется. Критичные нагрузки сохраняют опору при конкуренции.
Когда использовать
Включайте координатор, когда:
- На одной базе сосуществуют разные нагрузки, и нужен верхний предел числа backend-соединений (
max_connectionsPostgreSQL, RAM, файловые дескрипторы). - Одна нагрузка имеет всплеск нагрузки, и вы хотите, чтобы она забирала простаивающие слоты у других, не вытесняя их навсегда.
- Вы работаете рядом с потолком соединений PostgreSQL и нуждаетесь в справедливой деградации, а не в обслуживании по принципу «кто первый встал, того и тапки».
Координатор не нужен, когда:
pool_sizeкаждого пользователя достаточно мал, чтобы их сумма комфортно укладывалась вmax_connectionsPostgreSQL.- Нагрузки предсказуемы и заранее размечены.
- Вы хотите простоту уровня PgBouncer.
max_db_connectionsбез вытеснения поддерживается, но не рекомендуется для общих баз.
Конфигурация
pools:
shared_db:
server_host: "127.0.0.1"
server_port: 5432
pool_mode: "transaction"
# Общий лимит на всех пользователей этого пула.
max_db_connections: 80
# Резерв сверх max_db_connections для коротких всплесков.
# Захватывается, только если в течение reserve_pool_timeout не нашлось idle-соединения.
reserve_pool_size: 16
reserve_pool_timeout: "3s"
# Страховка для пользователя: соединения никогда не вытесняются у него, даже под давлением.
# Сумма по пользователям должна быть <= max_db_connections.
min_guaranteed_pool_size: 5
# Льготный период для вытеснения: соединения младше этого возраста не вытесняются.
# Защищает от колебания, когда нагрузка кратковременно простаивает.
min_connection_lifetime: "30s"
users:
- username: "fast_app"
password: "md5..."
pool_size: 40
- username: "batch_job"
password: "md5..."
pool_size: 60
Эффективный потолок: max_db_connections + reserve_pool_size = 96. Резерв поглощает доли секундные пики; если пик затягивается, включается вытеснение.
Как выбирается донор
Когда пользователь запрашивает новый бэкенд, а лимит уже достигнут:
- Найти кандидатов с idle-соединениями. Пользователь, у которого все соединения активны, не может стать донором — его работа в полёте.
- Пропустить защищённых. Пользователь ниже
min_guaranteed_pool_sizeисключается. - Пропустить недавно созданные соединения. Соединения младше
min_connection_lifetimeне вытесняются (это снижает колебание при коротких idle-промежутках). - Ранжировать по излишку. Пользователи с наибольшим числом idle-соединений сверх
min_guaranteed_pool_sizeполучают высший ранг. - Tiebreaker — p95 времени транзакции. Среди пулов с одинаковым излишком первым отдаёт медленный. Их соединения, скорее всего, простаивали потому, что следующий запрос ещё готовится на стороне приложения.
Выбранное idle-соединение закрывается; запрашивающий пользователь получает свежее соединение из PostgreSQL.
Observability
SHOW POOL_COORDINATOR показывает текущее состояние по каждой базе:
database | max_db_conn | current | reserve_size | reserve_used | evictions | reserve_acq | exhaustions
shared_db | 80 | 78 | 16 | 2 | 142 | 18 | 0
evictionsбыстро растёт — один пользователь голодает раз за разом. Поднимитеmax_db_connectionsили задайте этому пользователюmin_guaranteed_pool_size.reserve_acqвысокий — всплески нормальны, но размер занижен; рассмотрите повышениеmax_db_connectionsвместо опоры на резерв.exhaustionsненулевой — резерв тоже был полным. Клиенты упёрлись вquery_wait_timeout, ожидая бэкенд. Поднимите лимит.
Prometheus: pg_doorman_pool_coordinator{type="..."} (gauge) и pg_doorman_pool_coordinator_total{type="evictions|reserve_acquisitions|exhaustions"} (counter). Смотрите Команды администратора и Справочник Prometheus.
Оговорки
- Координатор работает только внутри одного пула (одной базы). Кросс-пуловые / кросс-баз ограничения не поддерживаются.
- Вытеснение выбирает idle-соединения; пользователь, удерживающий все соединения в длинных транзакциях, не может стать донором, и другие пользователи могут голодать. Если ваша форма нагрузки именно такая — поднимите
max_db_connectionsили разделите нагрузки. min_guaranteed_pool_size— это нижняя граница для вытеснения, а неmin_pool_sizeдля прогрева. Эти соединения пул всё равно создаёт по требованию.- Задавать
max_db_connectionsбезmin_guaranteed_pool_size— это режим PgBouncer: работает, но мелкие пользователи голодают под давлением. Для общих баз всегда задавайте оба.
Куда дальше
- Как подобрать размер пула с разобранными примерами: Пул под нагрузкой → Согласование лимита с PostgreSQL.
- Тюнинг под нагрузкой: Пул под нагрузкой → Параметры тюнинга.
- Чтение вывода администратора: Команды администратора → SHOW POOL_COORDINATOR.
- Режимы пула (транзакционный против сессионного): Режимы пула.