Управление пулом подключений
PostgreSQL имеет ресурсоемкую архитектуру обработки соединений. Каждое входящее соединение создает новый серверный процесс. Это неэффективно, если речь идет о большом количестве подключений в производственном окружении. Когда клиент отправляет запрос к серверу PostgreSQL, создается соединение с базой данных. Пока сервер не ответит клиенту, соединение остается открытым. Под каждое из таких соединений выделяется память на сервере. Если соединения открываются достаточно часто, это может приводить к проблемам. Вот почему необходим PgBouncer. PgBouncer — это программа, управляющая пулом соединений PostgreSQL, которая позволяет увеличивать количество соединений без снижения производительности.
ПРИМЕЧАНИЕ
PgBouncer доступен в версии ADPG Enterprise. См. Настройка PgBouncer.
|
Как ADPG/PostgreSQL устанавливает соединения
ADPG/PostgreSQL реализует клиент-серверную модель по схеме "один процесс для одного пользователя". В этой модели каждый клиентский процесс подключается к одному серверному процессу. Поскольку изначально не определено, сколько соединений будет установлено, сервер PostgreSQL должен использовать процесс-супервизор, который запускает новый процесс каждый раз, когда запрашивается соединение. Этот процесс-супервизор называется postmaster и прослушивает указанный порт TCP/IP на предмет входящих соединений. Всякий раз, когда он обнаруживает запрос на соединение, он запускает новый backend-процесс. Эти серверные процессы взаимодействуют друг с другом и с другими процессами экземпляра сервера (a server instance), используя семафоры и общую память (shared memory) для обеспечения целостности данных при конкурентном доступе к ним. Каждый из этих серверных процессов может расширяться в зависимости от данных, к которым он обращается.
Несмотря на то, что под каждый новый backend-процесс выделяется память, количество доступной памяти не является основным ограничивающим фактором. Более тонкий и важный момент заключается в том, что postmaster и его внутренние процессы совместно используют память для коммуникации, и некоторые части этого общего пространства являются глобальными узкими местами. Например, в PostgreSQL существует структура (PROC_HDR
), которая отслеживает каждый текущий процесс или транзакцию. Операции, которые происходят в любом backend-процессе, требуют прохождения всего списка процессов или транзакций, сохраненных в этой структуре. Для добавления нового процесса используется эксклюзивная блокировка. Совокупный эффект заключается в том, что производительность любого backend-процесса обратно пропорциональна количеству всех активных backend-процессов в системе.
Конфигурационный параметр ADPG/PostgreSQL max_connections
определяет максимальное количество одновременных подключений к серверу. Значение по умолчанию — 100
. С большой долей вероятности такого количества подключений может быть недостаточно в производственном окружении.
Как работает PgBouncer
PgBouncer — это утилита, которая управляет пулом соединений. Клиентское приложение может подключиться к PgBouncer, как если бы это был сервер ADPG/PostgreSQL.
Когда PgBouncer получает запрос на клиентское соединение, он выполняет аутентификацию от имени сервера PostgreSQL. PgBouncer поддерживает все механизмы аутентификации, которые доступны в PostgreSQL. Важным моментом является то, что PgBouncer кеширует соединения.
Если аутентификация прошла успешно, PgBouncer проверяет наличие кешированного соединения с комбинацией тех же имени пользователя и базы данных. Если кешированное соединение найдено, PgBouncer возвращает соединение клиенту. Если соединение не найдено, PgBouncer создает новое соединение. Эта операция не должна нарушать ограничения, установленные в следующих параметрах: default_pool_size
, max_client_conn
, max_db_connections
и max_user_connections
. Все эти значения можно определить в настройках PgBouncer. Если создание нового соединения нарушает какие-либо ограничения, PgBouncer ставит соединение в очередь до тех пор, пока не появится возможность открыть новое, если только не превышено значение max_client_conn
. Превышение значения max_client_conn
прерывает соединение.
В режиме transaction
или statement
операции, следующие за аутентификацией, выполняются только тогда, когда клиент начинает выполнять транзакцию или оператор соответственно. Режимы пула PgBouncer описаны ниже.
Прежде чем вернуть соединение в пул, PgBouncer выполняет запрос сброса, чтобы удалить всю информацию о сессии. Такой подход делает безопасным совместное использование соединений клиентами.
PgBouncer может помочь оптимизировать:
-
сетевой трафик;
-
накладные расходы на запуск нового серверного процесса и аутентификацию.
PgBouncer не поддерживает автоматическую балансировку нагрузки или режим высокой отказоустойчивости, но ADPG Enterprise Edition предоставляет эти функции. См. Балансировка нагрузки.
PgBouncer имеет следующие преимущества:
-
Не требует изменения кода на стороне клиента.
-
Предоставляет сквозную аутентификацию. PgBouncer может безопасно аутентифицировать пользователя, не имея доступа к его паролям. Это делает PgBouncer более безопасным и простым в обслуживании — не нужно обновлять PgBouncer каждый раз, когда пользователь обновляет свой пароль.
-
Представляет собой одиночный процесс, и все команды клиента и ответы сервера проходят через него без какой-либо обработки. Следовательно, он занимает небольшой объем памяти.
-
Может значительно улучшить количество транзакций в секунду, которые обрабатывает сервер, и хорошо масштабируется для многочисленных клиентов.
Режимы PgBouncer
Режимы PgBouncer позволяют пользователю решать, когда соединение должно быть возвращено в пул. Доступны следующие режимы:
Установить нужный режим можно на вкладке Primary Configuration сервиса ADPG. См. Настройка PgBouncer.
Session
В режиме пула session
соединение возвращается в пул, когда клиент завершает сессию. Это режим по умолчанию. Его использование сокращает время и ресурсы, необходимые для установления соединений и аутентификации пользователей.
Transaction
В режиме transaction
соединение возвращается в пул, когда клиент завершает транзакцию. Нет никакой гарантии, что две транзакции, выполняемые на одном и том же клиентском соединении PgBouncer, будут выполняться на одном и том же серверном соединении PgBouncer. Соединение с сервером назначается клиентскому соединению всякий раз, когда клиент начинает новую транзакцию, и освобождается в пул, когда клиент завершает транзакцию, например, с использованием ROLLBACK
или COMMIT
, a не тогда, когда клиент отключается.
Обратите внимание, что в PostgreSQL если транзакция не запускается явно, каждый запрос выполняется в виде индивидуальной транзакции. См. Transactions.
Режим transaction
обеспечивает лучшую производительность и позволяет сократить количество простаивающих транзакций, в дополнение к сокращению времени, затрачиваемого на установление соединений и аутентификацию пользователей.
В этом режиме необходимо быть осторожным при использовании последовательностей, рекомендательных блокировок и %_SHARED
в функциях PL/Perl. Кроме того, планы запросов, созданные операторами PREPARE, кешируются и существуют вне транзакции. Их использование в режиме transaction
может привести к ошибкам или неожиданным результатам.
Полный список функционала PostgreSQL, основанного на специфике сессий, который не поддерживается в режиме transaction
:
-
опция
WITH HOLD CURSOR
команды DECLARE; -
опции
ON COMMIT PRESERVE ROWS
иON COMMIT DELETE ROWS
команды CREATE TABLE для временных таблиц; -
LOAD;
-
рекомендательные блокировки уровня сессии.
За дополнительной информацией обратитесь к статье PgBouncer features.
Statement
В режиме statement
соединение возвращается в пул сразу после выполнения оператора. Это самый агрессивный режим. Его можно рассматривать как пул транзакций с одним ограничением: транзакции с несколькими операторами не допускаются. Режим statement
предназначен для обеспечения режима автоматической фиксации на клиенте, в первую очередь ориентированного на PL/Proxy.