Повышение масштабируемости PostgreSQL: внедрение пула соединений PgBouncer
Используйте PgBouncer для снижения накладных расходов на соединения PostgreSQL, выбора режима пула, настройки размеров пулов и мониторинга нагрузки клиентов.
Повышение масштабируемости PostgreSQL: внедрение пула соединений PgBouncer
PostgreSQL использует один серверный процесс на каждое клиентское соединение. Эта модель надежна, но становится дорогостоящей, когда веб-приложение открывает сотни или тысячи в основном простаивающих соединений.
PgBouncer располагается между вашим приложением и PostgreSQL, поддерживая меньший пул серверных соединений и позволяя многим клиентам повторно использовать их. Результат — снижение накладных расходов на соединения и более предсказуемое использование памяти базы данных.
Узкое место: накладные расходы на соединения в PostgreSQL
PostgreSQL использует модель «один процесс на соединение». Будучи высокостабильной и обеспечивающей изоляцию, эта архитектура вносит значительные накладные расходы при нагрузке:
- Потребление ресурсов: Каждое новое соединение требует от сервера создания нового серверного процесса, потребляя память и ресурсы ЦП. Сотни или тысячи простаивающих соединений без необходимости удерживают оперативную память.
- Медленное установление: Установление нового соединения включает рукопожатие по сети, аутентификацию и инициализацию процесса, добавляя заметную задержку к запросам приложения, особенно тем, которые часто открывают и закрывают соединения.
- Ограничения масштабирования: Эти требования к ресурсам устанавливают эффективный предел количества одновременных соединений, которые сервер PostgreSQL может реально обрабатывать до падения производительности.
Знакомство с PgBouncer: легковесный прокси
PgBouncer действует как легковесный прокси-сервер, расположенный между клиентскими приложениями и сервером базы данных PostgreSQL. Его основная функция — поддерживать постоянное, фиксированное количество открытых соединений с сервером PostgreSQL, объединяя и повторно используя эти соединения для временных клиентских запросов приложений.
Такой подход дает два критических преимущества:
- Снижение накладных расходов: Сервер PostgreSQL видит только фиксированный пул соединений, поддерживаемый PgBouncer, что устраняет дорогостоящий цикл создания процесса на каждое соединение для входящих клиентских запросов.
- Увеличение пропускной способности: Повторно используя установленные соединения, PgBouncer минимизирует время аутентификации и инициализации соединения, что приводит к значительно более высокой пропускной способности приложения и меньшей задержке.
Понимание режимов пула PgBouncer
Эффективность PgBouncer во многом зависит от выбранного режима пула. PgBouncer предлагает три основных режима, каждый из которых подходит для разных архитектур приложений и требований к параллелизму.
1. Сессионный пул (pool_mode = session)
Сессионный пул — это режим по умолчанию и самый безопасный. Как только клиент подключается, PgBouncer выделяет этому клиенту соединение из пула до тех пор, пока клиент не отключится. Соединение возвращается в пул только после явного закрытия сессии клиентом.
- Сценарий использования: Приложения, которые сильно полагаются на специфичные для сессии функции (например, подготовленные операторы, временные таблицы, команды
SETдля пользовательских переменных). - Плюсы: Самый безопасный, полностью совместим со всеми функциями PostgreSQL.
- Минусы: Наименее эффективный пул, так как соединения удерживаются даже во время простоя клиента.
2. Транзакционный пул (pool_mode = transaction)
Транзакционный пул обычно рекомендуется для высоконагруженных веб-приложений, особенно тех, которые используют stateless API. Серверное соединение выделяется клиенту только на время одной транзакции (от BEGIN до COMMIT/ROLLBACK). Как только транзакция завершается, соединение немедленно возвращается в пул для повторного использования другим ожидающим клиентом.
- Сценарий использования: Короткие, частые транзакции, характерные для OLTP-систем и микросервисов.
- Плюсы: Высокоэффективное использование серверных ресурсов.
- Минусы: Требует от приложений тщательного управления транзакциями. Изменения состояния на уровне сессии (например,
SET extra_float_digits = 3) будут потеряны между транзакциями или могут «утечь» к другим клиентам.
Предупреждение о транзакционном пуле
При транзакционном пуле избегайте состояния сессии, такого как временные таблицы, изменения на уровне сессии с помощью
SET, сессионные консультативные блокировки и долгоживущие подготовленные операторы. PgBouncer сбрасывает серверные соединения между клиентами, но транзакционный пул все равно требует проверки совместимости приложения.
3. Пуловый режим на уровне операторов (pool_mode = statement)
Пуловый режим на уровне операторов — самый агрессивный режим. Серверное соединение возвращается в пул после выполнения каждого отдельного оператора. Этот режим эффективно предотвращает использование многооператорных транзакций и является очень ограничительным.
- Сценарий использования: Узкоспециализированные, только для чтения нагрузки, где транзакции явно запрещены или не нужны.
- Плюсы: Максимизирует повторное использование соединений.
- Минусы: Нарушает все транзакции. Подходит только для сред, где гарантированно не используются транзакции.
Настройка и начальная конфигурация PgBouncer
1. Установка
PgBouncer часто доступен в стандартных репозиториях дистрибутивов:
# На Debian/Ubuntu
sudo apt update && sudo apt install pgbouncer
# На RHEL/CentOS
sudo dnf install pgbouncer
2. Файлы конфигурации
PgBouncer в основном использует два файла конфигурации, обычно расположенных в /etc/pgbouncer/:
pgbouncer.ini: Основная конфигурация, определяющая базы данных, лимиты пула и режимы работы.userlist.txt: Определяет пользователей и пароли, которые PgBouncer использует для аутентификации на сервере PostgreSQL.
3. Определение пользователей (userlist.txt)
В целях безопасности PgBouncer не читает напрямую таблицу pg_authid PostgreSQL. Вы должны вручную определить пользователей, с которыми он может аутентифицироваться. Убедитесь, что этот файл защищен (например, принадлежит пользователю pgbouncer и имеет ограниченные права доступа).
"app_user" "md5<md5-хэш>"
"admin_user" "another_hash"
Пароли в открытом виде возможны в некоторых конфигурациях аутентификации, но предпочтительнее использовать хэшированную или более надежную аутентификацию, если ваши версии PgBouncer и PostgreSQL это поддерживают. Для устаревшей MD5-аутентификации сохраняемое значение — это md5 плюс MD5-хэш пароля и имени пользователя, а не просто пароль.
4. Настройка pgbouncer.ini
Файл pgbouncer.ini определяет поведение пулера. Ниже приведен пример, адаптированный для типичной настройки веб-приложения с использованием транзакционного пула.
[databases]
# Определение строки подключения клиента:
# <имя базы данных> = host=<ip_сервера_pg> port=<порт_pg> dbname=<имя_бд> user=<пользователь_аутентификации_pgbouncer>
myappdb = host=10.0.0.5 port=5432 dbname=productiondb user=pgbouncer_service
[pgbouncer]
; Конфигурация прослушивания
listen_addr = *
listen_port = 6432
; Конфигурация аутентификации
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
; Режим пула (устанавливается в зависимости от потребностей приложения)
pool_mode = transaction
; DISCARD ALL — это запрос сброса по умолчанию для сессионного пула.
; При транзакционном пуле тщательно тестируйте, прежде чем полагаться на состояние сессии.
server_reset_query = DISCARD ALL
; Лимиты и размеры соединений
; Максимальное общее количество клиентских соединений к PgBouncer
max_client_conn = 1000
; Максимальное количество соединений, которые PgBouncer держит открытыми на базу данных (размер пула)
default_pool_size = 20
; Максимальное количество соединений, разрешенных в пуле в целом по всем базам данных
max_db_connections = 100
; Когда пул исчерпан, зарезервировать это количество слотов
reserve_pool_size = 5
; Логирование и администрирование
admin_users = postgres, admin_user
stats_users = postgres
Мониторинг и администрирование
PgBouncer предоставляет псевдобазу данных с именем pgbouncer, которая позволяет администраторам отслеживать статус пулера, статистику и соединения в реальном времени. Вы подключаетесь к порту прослушивания PgBouncer (например, 6432), используя одного из определенных admin_users.
psql -p 6432 -U admin_user pgbouncer
Ключевые административные команды:
| Команда | Описание | Примечание по использованию |
|---|---|---|
SHOW STATS; |
Отображает статистику соединений (запросы, байты, общая длительность). | Полезно для анализа производительности. |
SHOW POOLS; |
Показывает состояние пулов для всех настроенных баз данных. | Следите за cl_active, sv_active, sv_idle. |
SHOW CLIENTS; |
Перечисляет все клиентские соединения, подключенные к PgBouncer. | |
RELOAD; |
Пытается перезагрузить конфигурацию без прерывания соединений. | |
PAUSE; |
Прекращает принимать новые запросы, ожидает завершения текущих транзакций. | Используется перед обслуживанием или обновлением PgBouncer. |
Советы по масштабированию
- Размещение: Установите PgBouncer на том же сервере, что и ваше приложение, или на выделенной, оптимизированной по сети машине, чтобы минимизировать задержку между приложением и пулером.
- Размер пула:
default_pool_sizeдолжен быть установлен в разумное число (часто 10-50), которое обычно намного меньше количества соединений, разрешенных на самом сервере PostgreSQL. Чрезмерный размер пула сводит на нет цель пулинга. - Лимиты клиентов: Используйте
max_client_conn, чтобы предотвратить перегрузку самого PgBouncer из-за шквала соединений. Это действует как надежный ограничитель на фронтенде.
Вывод
PgBouncer наиболее полезен, когда ваше приложение имеет много короткоживущих или простаивающих соединений. Выберите наименее агрессивный режим пула, который может выдержать ваше приложение, держите пулы сервера PostgreSQL достаточно маленькими, чтобы защитить базу данных, и следите за SHOW POOLS; на предмет ожидающих клиентов, прежде чем пользователи почувствуют замедление.