Что такое PGBalancer в PostgreSQL?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
PgBouncer в PostgreSQL — управление пулом соединений
Вопрос, вероятно, имеет в виду PgBouncer (не PGBalancer), который является одним из самых популярных инструментов для управления пулом соединений в PostgreSQL. PgBouncer — это легковесный connection pooler, написанный на C, который действует как промежуточный слой между приложениями и базой данных.
Зачем нужен PgBouncer?
PostgreSQL имеет ограничение на количество одновременных соединений (по умолчанию около 100). Если каждое клиентское подключение создаёт прямое соединение с БД, база данных быстро исчерпает лимит соединений.
Проблема без PgBouncer:
- Приложение с 1000 пользователей создаёт 1000 соединений с БД
- Каждое соединение использует память на сервере БД
- PostgreSQL исчерпывает лимит соединений → новые запросы отклоняются
Решение с PgBouncer:
- 1000 пользователей подключаются к PgBouncer
- PgBouncer переиспользует небольшой пул соединений (например, 20-50) к БД
- Пользователи конкурируют за места в пуле, но БД не перегружается
Принцип работы
Приложение 1 ──┐
Приложение 2 ──┤
Приложение 3 ──┼──> PgBouncer ──> PostgreSQL (5 соединений)
Приложение 4 ──┤
Приложение 5 ──┘
Установка и конфигурация
На Linux:
sudo apt-get install pgbouncer
Конфиг pgbouncer.ini:
[databases]
# Имя БД в приложении = реальное имя на сервере
myapp = host=localhost port=5432 dbname=mydb
[pgbouncer]
# Количество соединений в пуле
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 25
min_pool_size = 10
reserve_pool_size = 5
reserve_pool_timeout = 3
# Логирование
logfile = /var/log/pgbouncer/pgbouncer.log
pidfile = /var/run/pgbouncer.pid
listen_port = 6432
listen_addr = 127.0.0.1
Режимы работы PgBouncer
1. Session Mode (сессионный режим)
pool_mode = session
- Одно клиентское соединение привязано к одному соединению в пуле на всю сессию
- Клиент получает одно и то же серверное соединение до отключения
- Если в пуле нет свободного соединения, клиент ждёт
- Использование: Когда клиент использует особенности сессии (временные таблицы, SET переменные)
2. Transaction Mode (транзакционный режим)
pool_mode = transaction
- Соединение переиспользуется после каждой завершённой транзакции
- Клиент может получить разные серверные соединения для разных транзакций
- Более эффективное использование пула
- Ограничение: Не поддерживает курсоры через транзакции, временные таблицы
3. Statement Mode (режим оператора)
pool_mode = statement
- Соединение освобождается после каждого SQL-оператора
- Максимально эффективное переиспользование
- Ограничение: Очень ограниченный; нельзя использовать многооператорные транзакции
Типичная конфигурация для Node.js приложения
[databases]
app_prod = host=db.prod.example.com port=5432 dbname=app_db
app_dev = host=localhost port=5432 dbname=app_dev
[pgbouncer]
# Режим: транзакционный идеален для REST API
pool_mode = transaction
# Максимум клиентских соединений
max_client_conn = 1000
# Размер пула: если приложение создаёт 500 соединений одновременно,
# нужно выделить достаточно соединений к БД
# Правило: min_pool_size * кол-во баз >= макс. параллельные транзакции
default_pool_size = 25
min_pool_size = 10
reserve_pool_size = 5
reserve_pool_timeout = 3
# Таймауты
server_lifetime = 3600
server_idle_timeout = 600
client_idle_timeout = 900
# Аутентификация
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
listen_port = 6432
listen_addr = 0.0.0.0
Использование с Node.js / Express
import { Pool } from 'pg';
// Подключаемся к PgBouncer, а не напрямую к PostgreSQL
const pool = new Pool({
host: 'localhost', // Адрес PgBouncer
port: 6432, // Порт PgBouncer (не 5432!)
database: 'myapp',
user: 'app_user',
password: 'secure_password',
max: 5, // Соединений в пуле приложения
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
export default pool;
Мониторинг PgBouncer
Подключение к админской консоли:
psql -h localhost -p 6432 -U pgbouncer pgbouncer
Полезные команды:
-- Показать статус пула
SHOW POOLS;
-- Показать статистику по клиентам
SHOW CLIENTS;
-- Показать статистику по серверам
SHOW SERVERS;
-- Показать состояние статистики
SHOW STATS;
-- Перезагрузить конфиг без перезагрузки
RELOAD;
-- Безопасно завершить все соединения
SHUTDOWN;
Пример мониторинга в приложении
import { Client } from 'pg';
async function checkPgBouncerHealth() {
const client = new Client({
host: 'localhost',
port: 6432,
database: 'pgbouncer',
user: 'pgbouncer',
password: 'pgbouncer_password',
});
try {
await client.connect();
// Показать статистику пула
const result = await client.query('SHOW POOLS');
console.log('PgBouncer pools:', result.rows);
// Проверить состояние
const stats = await client.query('SHOW STATS');
const totalRequests = stats.rows.reduce((sum, row) => sum + row.xact_count, 0);
return {
healthy: true,
totalRequests,
pools: result.rows
};
} catch (error) {
console.error('PgBouncer health check failed:', error);
return { healthy: false };
} finally {
await client.end();
}
}
Проблемы и решения
Проблема: "no more connections"
Решение: Увеличить default_pool_size или max_client_conn
default_pool_size = 40 # Вместо 25
max_client_conn = 2000 # Вместо 1000
Проблема: "server closed the connection unexpectedly"
Решение: Увеличить server_lifetime или уменьшить server_idle_timeout
server_lifetime = 7200 # Переподключение каждые 2 часа
server_idle_timeout = 900 # Закрывать неиспользуемые за 15 минут
Проблема: Временные таблицы не работают в транзакционном режиме
Решение: Либо переключиться на session mode, либо использовать постоянные таблицы
Альтернативы PgBouncer
- Pgpool-II — более мощный, поддерживает балансирование нагрузки и репликацию
- Pooled connections в облаках — AWS RDS Proxy, Google Cloud SQL Proxy, Heroku Postgres Stunnel
Best Practices
1. Рассчитай размер пула правильно
pool_size = (core_count * 2) + effective_spindle_count
// Для 4-ядерного сервера: (4 * 2) + 1 = 9 соединений в пуле
2. Мониторь метрики PgBouncer
// В Prometheus/Grafana
SELECT
datname,
COUNT(*) as connection_count,
state
FROM pg_stat_activity
GROUP BY datname, state;
3. Используй statement mode осторожно
// Проблемный код со statement mode:
const result1 = await pool.query('BEGIN');
const result2 = await pool.query('SELECT 1');
// Если между BEGIN и SELECT переключится соединение в пуле → ошибка!
4. Установи правильные таймауты
# Слишком короткий таймаут = часые переподключения
client_idle_timeout = 900 # 15 минут — хороший баланс
server_idle_timeout = 600 # 10 минут
PgBouncer — это essential инструмент для production-приложений, работающих с PostgreSQL, позволяющий масштабировать количество клиентов без перегрузки базы данных.