В этой статье сравнивается архитектура трех пулов: язык, режимы пула, одно- или многоарендная модель, функции, выходящие за рамки чистого пула. Tembo и PkgPulse опубликовали числовые сравнения этих трех инструментов, но мы сами не воспроизвели ни одного из их измерений. Наша редакционная позиция в отношении тестов, подробно описанная в нашей методологии тестирования , заключается в том, чтобы никогда не публиковать повторно данные, которые мы не проверили сами. Вместо этого вы найдете здесь: фактическую архитектуру каждого инструмента и то, как Aurabase на самом деле маршрутизирует трафик Postgres, проверенный раздел за разделом в исходном коде.
- PgBouncer (C) остается наиболее проверенным пулером и лучше всего интегрирован с Kubernetes: CloudNativePG напрямую использует его для своего ресурса
Pooler. - Supavisor (Elixir, проект Supabase) решает другую задачу: обслуживает тысячи баз данных из одного сервиса, а не один пулер на каждую базу данных.
- PgCat (Rust) добавляет к необработанному пулу сегментирование приложений, балансировку нагрузки между репликами и автоматический переход на другой ресурс.
- В репозитории Aurabase показано, что PgBouncer используется на двух уровнях: совместное развертывание для общего парка и ресурс
Pooler, управляемый CloudNativePG для каждого выделенного клиента. Оба работают в режиме транзакций. - PostgREST и административный пул
aura-dbдобровольно остаются в прямом соединении с Postgres, минуя пул: объединение в пул транзакций нарушит перезагрузку их схемы и блокировки сеансов.
Три игрока в пул, три философии
PgBouncer сводит к минимуму, Supavisor создает многопользовательские пулы, PgCat добавляет сетевые функции к необработанному пулу. Ни один из трех не является прямой заменой двух других, хотя их часто сравнивают по терминам на одних и тех же страницах.
| Язык | C | Эликсир (ЛУЧ) | Ржавчина |
|---|---|---|---|
| Режимы объединения | Сессия, транзакция, заявление | Сессия, транзакция | Сессия, транзакция, заявление |
| Модель аренды | Один целевой кластер на каждый экземпляр, предназначенный для одного клиента. | Нативный мультитенант: сервис для многих баз данных | Целевой кластер, сегментирование по ключу раздела |
| Помимо объединения | Никаких дополнительных функций, намеренно минимальный | HTTP API администратора, динамическая регистрация арендатора | Шардинг, балансировка нагрузки и переключение между репликами |
| Нативная интеграция с Kubernetes | Да: Пул ресурсов CloudNativePG | На сегодняшний день не задокументировано изначально | На сегодняшний день не задокументировано изначально |
| Источник | Исторический стандарт пула Postgres | Создано Supabase для собственного мультитенантного облака. | Родился в Instacart, сегодня поддерживается PostgresML. |
Столбцы по порядку: PgBouncer, Supavisor, PgCat. Характеристики архитектуры соответствуют официальным документам каждого проекта и должны быть подтверждены в развертываемой вами версии, экосистема в этом отношении быстро развивается.
Исторический стандарт, легкий и интегрированный в Kubernetes.
PgBouncer делает только одно: пул соединений Postgres без каких-либо дополнительных функций. Эта намеренно узкая область применения во многом объясняет его долговечность и его принятие в качестве основного строительного блока в большинстве стеков Postgres, находящихся в производстве.
Доступны три режима объединения. В режиме сеанса на каждое клиентское соединение открывается одно соединение с сервером, самое разрешающее. Режим транзакции повторно использует соединение сервера между несколькими клиентами, освобождаемое на каждом конце транзакции. Режим операторов идет еще дальше и редко используется в производстве. Именно режим транзакций приносит реальную выгоду от объединения, но он налагает строгие правила. Любое состояние сеанса (переменныеSET, консультативные блокировки, LISTEN/NOTIFY) не сохраняется после транзакции. Мы подробно рассказываем об этих правилах и их подводных камнях в нашей специальной статье о режиме пула транзакций в PgBouncer.
Исторически являющийся однопроцессным экземпляром PgBouncer по умолчанию использует одно ядро ЦП. Запуск нескольких экземпляров за одним и тем же портом (через SO_REUSEPORT) — это более поздняя эволюция проекта, а не первоначальная особенность дизайна. Что касается аутентификации, PgBouncer поддерживает настраиваемую auth_query— функцию SQL, выполняемую при каждом соединении для динамического разрешения пароля роли. Этот механизм позволяет избежать зависимости от статического файла, в котором заранее указан каждый пользователь. Именно этот механизм Aurabase использует для своих ролей в каждом проекте (раздел 05).
PgBouncer — это пулер, который CloudNativePG изначально развертывает за своим ресурсом Pooler. В кластере Postgres, управляемом оператором CloudNativePG, активация управляемого пулера на практике эквивалентна активации PgBouncer без его ручной настройки.
Облачный многопользовательский пул Supabase
Supavisor решает проблему, для решения которой PgBouncer никогда не предназначался в таком масштабе. Это предполагает обслуживание очень большого количества отдельных баз данных арендаторов с помощью одной службы, а не одного экземпляра пула на каждую базу данных. Написанный на Elixir и выполненный на виртуальной машине Erlang (BEAM), проект разрабатывается и поддерживается Supabase с открытым исходным кодом в собственном репозитории GitHub.
Нативная мультиарендная модель представляет собой настоящее структурное отличие. Если классическому парку PgBouncer требуется один процесс (или набор выделенных подключений) для каждой целевой базы, Supavisor работает по-другому. Он динамически регистрирует клиентов через интерфейс администрирования HTTP и направляет каждое входящее соединение в нужную базу данных без перезапуска службы. Именно по этой причине Supabase перенесла свои собственные облачные проекты с PgBouncer на Supavisor. Классический пуловый кластер, по одному на каждую базу данных, не масштабируется до мультитенантного облака, в котором размещаются сотни тысяч проектов.
У этого архитектурного выбора есть документально подтвержденный недостаток. Паритет функций с PgBouncer в сложных случаях стабилизировался после запуска проекта. Два примера: определенное поведение LISTEN/NOTIFYи точное управление подготовленными операторами в режиме транзакции. Проверьте свою версию перед миграцией, если ваше приложение зависит от этих конкретных вариантов поведения.
Аутсайдер Rust: встроенное шардинг и балансировка нагрузки
PgCat явно позиционируется как альтернатива PgBouncer, написанная на Rust. Он добавляет сетевые функции к классическому пулу, которые не встроены ни в PgBouncer, ни в Supavisor. В частности, три: сегментирование приложения по ключу раздела, балансировка нагрузки между репликами чтения и автоматический переход на другой ресурс после отказавшей реплики. Проект родился в Instacart, а сегодня его переняла и поддерживает PostgresML.
Конкретно, PgCat может играть роль, которую обычно выполняют два отдельных уровня: средство создания пула соединений и прокси-сервер приложения для маршрутизации между несколькими экземплярами Postgres. Команда, которая уже вручную сегментировала свои данные, может упростить свой код с помощью PgCat. То же самое и с логикой распределения чтения между репликами, разработанной внутри компании: ее непосредственно заменяет выделенный сетевой уровень.
Существует и противоположный компромисс: PgCat — более молодой проект с гораздо меньшей экосистемой документации и обратной связи, чем PgBouncer. Принятие его функций сегментирования и аварийного переключения также означает согласие зависеть от зрелости этого конкретного компонента, а не только от его мощности пула.
Что показывает код Aurabase: PgBouncer везде, за исключением случаев, когда объединение транзакций нарушает все
Репозиторий Aurabase развертывает PgBouncer на двух отдельных уровнях, оба в режиме транзакций. Для общего парка диаграмма Helm определяет выделенное развертывание PgBouncer перед общей плоскостью данных (deploy/helm/aurabase/templates/infra/pgbouncer.yaml, изображение edoburu/pgbouncer). Для клиента в выделенном экземпляре поставщик создает ресурс Pooler, управляемый CloudNativePG (deploy/cnpg/tenant-pooler.yaml, визуализируемый k8s_tenant.rs). Ни один из них не использует Supavisor или PgCat. Код не документирует явное сравнение, предшествовавшее этому выбору. С другой стороны, он демонстрирует глубокую и уже работающую интеграцию с экосистемой CloudNativePG, что соответствует тому факту, что PgBouncer является встроенным блоком пула.
Однако не все проходит через пулер, и это осознанный выбор, задокументированный в самом коде. PostgREST остается подключенным к Postgres в реальном времени, а не через PgBouncer. В комментарии к диаграмме Helm четко указана причина: объединение транзакций нарушит перезагрузку схемы, которая зависит от LISTEN на канале pgrst. Этот механизм несовместим с переработанными серверными соединениями между клиентами. Пул администрированияaura-db (схема, DDL, блокировки рекомендаций сеанса) также остается в прямом соединении по той же основной причине. SET search_path, не относящийся к области транзакций, и блокировки сеансов не сохраняются в пуле режима транзакций.
Аутентификация осуществляется по шаблону auth_query, описанному в разделе 02: AUTH_QUERY: SELECT * FROM pgbouncer.user_lookup($1)без статического файла userlist.txt. Это то, что позволяет ролям, динамически создаваемым для каждого проекта (project_<uuid>_authenticator), проходить аутентификацию через PgBouncer без повторного развертывания средства объединения для каждого нового проекта.
Комментарий проверки работоспособности PgBouncer в локальном Kubernetes документирует реальную, уже исправленную ошибку. Запуск pg_isready против PgBouncer проверяет только подтверждение прокси-сервера, но не фактическое соединение с серверной частью Postgres, которую он ретранслирует. PgBouncer отвечает, «принимая соединения», даже когда серверная часть остановлена, ставя запросы в очередь. Результат, наблюдаемый во время разрушающего теста: служба оставалась healthy в течение 5 циклов подряд, в то время как Postgres был недоступен. Исправление заменяет проверку настоящим сквозным запросом psql через пул, вплоть до серверной части. Результат после исправления, в том же воспроизведенном тесте: unhealthy обнаружен за 7 циклов, примерно 35 секунд.
И последняя деталь, незначительная, но показательная: диаграмма Хелма по умолчанию закрепляет edoburu/pgbouncer:v1.24.1-p1, тогда как локальный стенд k3d использует v1.25.2-p0. Это не архитектурный выбор, а просто небольшое отсутствие синхронизации версий между двумя средами, такие детали, которые проверка кода улавливает быстрее, чем сообщение в блоге. Мы документируем все как есть, а не приукрашиваем. Подробную информацию о секционировании схемы, которую обслуживает этот пул, см. в нашей статье омноготенантной изоляции RLS.
Как выбрать между тремя
Выбирайте PgBouncer, если…
- Кластер Postgres, управляемый CloudNativePG или Kubernetes в целом.
- Вам нужен самый проверенный и хорошо документированный пулер
- Целевая база для каждого экземпляра пулера подходит вам
Выбирайте Supavisor, если…
- Сотни или тысячи баз за одним и тем же сервисом
- Необходимо регистрировать арендаторов динамически через API, без передислокации.
- Уже в экосистеме Supabase или готов зависеть от нее
Выбирайте PgCat, если…
- Совместное использование приложений уже реализовано или запланировано на уровне пула.
- Реплика балансировки нагрузки и аварийного переключения без отдельного уровня приложений
- Комфортно работать с более молодым проектом, менее документированным, чем PgBouncer.
Какой бы пул не был выбран, он не заменяет размер самого Postgres. Размер пула и сервер max_connections следует рассматривать вместе, а не друг за другом. Большой пул перед слишком низким max_connections просто сдвигает насыщенность с одного уровня на другой. В нашем руководстве по настройке max_connections подробно описана формула определения размера, которую следует применять перед установкой размера вашего пула.
Что нас спрашивают чаще всего
Универсального пулера не существует, он только хорошо подходит для вашей аренды.
PgBouncer, Supavisor и PgCat решают три варианта одной и той же проблемы, а не три версии одного и того же инструмента. PgBouncer остается самым безопасным выбором, если ваша платформа уже использует Kubernetes и CloudNativePG или когда вам просто нужен наиболее документированный пул. Супавайзер становится актуальным за пределами определенного количества баз, обслуживающих одну и ту же службу. PgCat стоит обойти, если вы пропустите сегментирование и аварийное переключение реплик на сетевом уровне, при условии, что вы согласны с зрелостью более молодого проекта.
Код Aurabase демонстрирует последовательный, а не нейтральный выбор: PgBouncer в режиме транзакций, на двух уровнях, общий парк и пул CNPG для каждого выделенного арендатора. Остаются два задокументированных исключения: для PostgREST и для администрирования схемы. Если вы хотите увидеть этот проект в действии, а не на бумаге, на нашей странице Performance документируется соответствующая методология измерения.