У нас есть два принципиально разных места, где можно расположить пул соединений: внутри самого приложения (Client-side) или перед базой данных (Proxy-side).
1. На стороне приложения
Пул живет прямо в оперативной памяти твоего сервиса. Самый популярный и быстрый пример в мире Java — HikariCP.
- Зачем нужен: Чтобы потоки внутри твоего приложения не блокировались в ожидании TCP-подключения к сети. Они мгновенно берут коннект из локальной памяти.
- Проблема: Если у тебя 50 подов микросервиса в Kubernetes, и в каждом HikariCP держит по 20 соединений, то база данных получит 1000 открытых подключений и ей может быть тяжко.
2. На стороне инфраструктуры
Пул живет на отдельном сервере, который стоит «щитом» перед БД. Примеры: PgBouncer, Odyssey (от Яндекса), AWS RDS Proxy.
- Зачем нужен: Защитить БД. Приложения стучатся в PgBouncer, думая, что это база. PgBouncer принимает тысячи легковесных входящих соединений, но держит с реальным Postgres всего 50-100 физических коннектов, мастерски перекидывая запросы между ними.
Иногда в микросервисной архитектуре используют оба пула одновременно. HikariCP мультиплексирует потоки приложения в сетевые вызовы, а PgBouncer мультиплексирует сетевые вызовы в реальные процессы базы данных.
Режимы работы внешнего пула
Посмотрим на примере PgBouncer.
Внешние пулеры могут жонглировать соединениями по-разному. Это важно понимать при настройке системы:
| Режим пулинга | Как работает | Особенности |
|---|---|---|
| Session Pooling | Реальное серверное соединение привязывается к клиенту на всё время жизни его сессии. | Самый безопасный, поддерживает все фичи БД. Но неэффективен для тысяч микросервисов. |
| Transaction Pooling | Соединение выдается клиенту только на время одной транзакции (BEGIN ... COMMIT), затем сразу отдается другому. |
Выжимает абсолютный максимум производительности. Минус: ломает работу Prepared Statements и временных таблиц. |
| Statement Pooling | Соединение отдается строго на один SQL-запрос. | Ломает транзакции с несколькими запросами. Используется редко (например, при AUTOCOMMIT). |
Резюме: Если ты пишешь на Java/Go/Python — обязательно настраивай локальный пул (ограничивай max_connections). Если система растет до десятков инстансов — ставь перед БД PgBouncer в режиме Transaction Pooling, предварительно отключив Prepared Statements в драйвере приложения.