Перейти к основному содержимому

Уровень 2.0

Предусловие:

  • Изучена лекция 1 «Управление расширениями»

В этом задании:

  • Назначение и механизм работы пулера соединений
  • Основные настройки в Pangolin Pooler
  • Аутентификация в Pangolin Pooler
  • Управление и мониторинг в Pangolin Pooler

Пулер соединений​

Проблемы большого количества соединений​

Как известно из курса DBA1, в архитектуре Pangolin используется процессная модель взаимодействия с клиентами — для каждого клиента в экземпляре сервера выделяется отдельный обслуживающий процесс.

Такая модель положительно влияет на надежность сервера, однако при большом количестве клиентов может негативно влиять на его производительность.

Основными причинами этого являются:

  • Высокая стоимость создания соединения (аутентификация, инициализация обслуживающего процесса)
  • Расходование ресурсов (в первую очередь памяти) обслуживающими процессами
  • Высокая стоимость создания снимков данных

Во-первых, при создании соединения необходимо пройти процедуру аутентификации и проверки прав доступа, что требует вычислительных ресурсов, особенно в случае организации шифрованных соединений.

Также необходимо проинициализировать обслуживающий процесс, в том числе выделить память и заполнить кеши в ней (например, кеши системного каталога).

Во-вторых, каждый обслуживающий процесс расходует память, в том числе, как было сказано выше, для кеширования данных.

В-третьих, как известно из курса DBA2, при создании снимков данных просматривается структура ProcArray, содержащая список всех обслуживающих процессов. С учетом того, что снимки данных создаются часто, их большое количество может негативно сказываться на общей производительности сервера.

Максимальное количество соединений с экземпляром сервера ограничивается параметром max_connections (по умолчанию 100). Его оптимальное значение зависит от многих факторов, таких как профиль нагрузки, количество ядер и объем доступной памяти. Обычно значение max_connections лежит в диапазоне от нескольких сотен до нескольких тысяч.

Большее количество соединений может привести к описанным проблемам производительности.

Указанные проблемы частично могут быть решены путем использования устойчивых соединений, когда одним клиентом длительное время удерживается соединение с экземпляром сервера. В этом случае уменьшается количество операций инициализации соединения и создания снимков данных, но не решается проблема расходования памяти обслуживающими процессами. Даже простаивающий обслуживающий процесс расходует вычислительные ресурсы.

Поэтому в таких случаях применяются дополнительные средства, реализующие механизм пула соединений.

Механизм пула соединений​

Механизм пула соединений подразумевает совместное использование клиентами некоторого небольшого количества долгоживущих соединений.

Эффективность такого механизма объясняется тем, что открытое соединение с экземпляром сервера, как правило, большую часть времени простаивает. Пул соединений позволяет нескольким клиентам совместно использовать одно соединение, минимизируя периоды простоя и повышая эффективность расходования вычислительных ресурсов сервера.

Реализуется такой подход с использованием специального программного обеспечения — пулера соединений (или по-другому — менеджера пулов соединений).

Пулер соединений выступает в роли посредника между клиентами и экземпляром сервера. Он удерживает небольшое количество соединений с экземпляром сервера и предоставляет их по мере необходимости клиентам.

Пулер соединений

Пулер соединений реализован в соответствии с клиент-серверным протоколом. Это позволяет ему представляться экземпляром сервера для клиентов и клиентами для экземпляра сервера.

Пулер соединений может быть развернут на различных узлах информационной системы.

Для обеспечения высокой скорости установки соединений пулер целесообразно размещать ближе к клиентам — на сервере приложений. При этом необязательно иметь пулер соединений в виде отдельного компонента. Многие серверы приложений и клиентские драйверы PostgreSQL предоставляют функциональность пулера соединений.

Однако, если в системе используется несколько серверов приложений, то для упрощения управления количеством соединений пулер целесообразно размещать на сервере СУБД. Для этой цели требуется использование отдельного пулера соединений.

В состав дистрибутива Pangolin входит пулер соединений в виде отдельного компонента c названием Pangolin Pooler.

Pangolin Pooler является доработанной версией утилиты с открытым исходным кодом PgBouncer, которая де-факто является стандартом управления пулами соединений.

Далее на примере Pangolin Pooler будут рассмотрены основные конфигурационные параметры для настройки пулера соединений, связанные с его использованием для ограничения разработки, методы аутентификации, а также имеющиеся средства мониторинга и управления.

Основные настройки в Pangolin Pooler​

Конфигурационный файл​

Основным конфигурационным файлом для настройки Pangolin Pooler является pangolin-pooler.ini, который обычно располагается в каталоге /etc/pangolin-pooler/.

В этом файле можно задать много параметров, с помощью которых в том числе можно настроить:

  • Подключение к пулеру и базам данных
  • Аутентификацию клиентов
  • Режим использования пулов
  • Ограничения на количество соединений
  • Доступ к консоли управления

Пример файла pangolin-pooler.ini с минимальными настройками приведен ниже:

;;;
;;; Pangolin Pooler configuration file
;;;
[databases]
* = host=localhost port=5432
[pgbouncer]
logfile = /opt/pangolin-pooler/log/pangolin-pooler.log
pidfile = /var/run/pangolin-pooler/pangolin-pooler.pid
listen_addr = localhost
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pangolin-pooler/userlist.txt
admin_users = student
pool_mode = transaction

Параметры сгруппированы по разделам, имена которых указываются в квадратных скобках (например, [databases]). Комментарии в файле начинаются с символа ; или #.

Режимы Pangolin Pooler​

Совместное использование соединения различными клиентами может выполняться в различных режимах. Режим пулинга задается параметром pool_mode, предусматривающим следующие значения:

  • session — пул сеансов (используется по умолчанию)
  • transaction — пул транзакций
  • statement — пул операторов

Пул сеансов предполагает предоставление клиенту соединения из пула на все время его сеанса взаимодействия с Pangolin Pooler.

Такой режим позволяет решить проблему высокой стоимости организации соединения, однако не решает проблем, связанных с простоем соединения. Поэтому режим пула сеансов имеет смысл только для коротких сеансов, в которых в идеале выполняется лишь одна транзакция, то есть исключена возможность простоя между транзакциями.

Пул транзакций является наиболее востребованным режимом работы пулера соединений. Он предполагает предоставление клиенту соединения из пула на время выполнения транзакции. После завершения транзакции соединение возвращается в пул. Для выполнения следующей транзакции в сеансе взаимодействия с пулером клиенту заново предоставляется соединение из пула.

Такой режим помимо решения проблемы высокой стоимости организации соединения также является эффективным с точки зрения утилизации соединений, поскольку не расходует ресурсы соединения в периоды простоя между транзакциями одного сеанса. Однако он накладывает на разработку некоторые ограничения, связанные с тем, что транзакции одного сеанса могут выполняться разными обслуживающими процессами.

Пул операторов подобен режиму пула транзакций, однако дополнительно запрещает выполнение транзакций, состоящих более чем из одного оператора. Поэтому применение данного режима на практике не очень целесообразно, так как ограничивает возможность использования преимуществ транзакций.

Ограничения режима пула транзакций​

Режим пула транзакций (впрочем, как и пула операторов) накладывает некоторые ограничения, которые необходимо учитывать при разработке.

Пул транзакций допускает выполнение транзакций одного клиентского сеанса в разных сеансах с экземпляром БД или, по-другому, разными обслуживающими процессами. Следовательно, функциональность, действие которой распространяется на весь сеанс, а не только на транзакцию, может работать некорректно.

К такой функциональности относятся:

  • PREPARE/EXECUTE/DEALLOCATE — подготовленные операторы
  • CREATE TEMP TABLE — создание временных таблиц (без конструкции ON COMMIT DROP)
  • SET/RESET — указание значений конфигурационных параметров
  • DECLARE .. WITH HOLD — определение курсора с удержанием между транзакциями
  • currval — получение текущего значения последовательности в сеансе
  • pg_advisory — рекомендательные блокировки на уровне сеанса
  • LOAD — загрузка разделяемых библиотек расширения
  • использование расширений, сохраняющих состояние на уровне сеанса
  • LISTEN/NOTIFY — межпроцессные уведомления

Стоит отметить, что подготовленные операторы все же могут быть использованы посредством Pangolin Pooler начиная с версии 5.1.0. Однако это возможно только на уровне клиент-серверного протокола, то есть за подготовку операторов должен отвечать драйвер для кого-либо языка программирования, формирующий сообщения протокола взаимодействия с Pangolin Pooler.

Описание использования подготовленных операторов в Pangolin Pooler приведено в документации.

Команды SQL PREPARE, EXECUTE и DEALLOCATE передаются пулером экземпляру сервера напрямую без понимания их смысла, поэтому их применение в пуле транзакций по-прежнему может вызывать проблемы.

Необходимо отметить, что использование процедур и функций на языке PL/PgSQL решает проблему подготовленных операторов, поскольку подготовка операторов в этом случае происходит на стороне сервера в автоматическом режиме.

Ограничения на количество соединений​

Как известно, подключение к экземпляру сервера выполняется от имени какой-либо роли к заданной базе данных.

По этой причине для каждой пары «роль—база данных» пулер использует отдельный пул соединений.

Общие ограничения на количество соединений, распространяющиеся на все имеющиеся пулы соединений, задаются в разделе [pgbouncer].

Предельное количество соединений в пуле для каждой такой пары задается параметром default_pool_size (по умолчанию 20).

Также с использованием параметра min_pool_size (по умолчанию 0) может быть задано минимальное количество удерживаемых соединений. Это позволяет сглаживать нагрузку при ее возобновлении после периода бездействия.

Если клиент запрашивает соединение из пула с заданной парой «роль—база данных» и оказывается, что свободных соединений нет, он становится в очередь и ожидает обслуживания.

При этом если через reserve_pool_timeout секунд (по умолчанию 5) клиенту так и не было предоставлено соединение из пула, то ему может быть назначено соединение из резервного пула, размер которого определяется значением параметра reserve_pool_size (по умолчанию 0, то есть резервный пул не используется).

Таким образом, клиент получает отказ в предоставлении соединения, если по прошествии reserve_pool_timeout секунд в резервном пуле не оказалось свободных соединений (или резервный пул вовсе не используется).

Общее количество соединений с одной базой данных (независимо от роли) может быть ограничено параметром max_db_connections (по умолчанию 0, то есть не ограничено), а общее количество соединений для одной роли (независимо от базы данных) — параметром max_user_connections (по умолчанию 0, то есть не ограничено).

Параметр max_client_conn ограничивает количество соединений с самим пулером. Его значение, по умолчанию равное 100, является совсем небольшим. Обычно его существенно увеличивают, иначе пулер становится бесполезным посредником (со 100 соединениями экземпляр сервера, как правило, вполне эффективно справляется). По тем же причинам значение max_client_conn должно быть существенно больше значения max_db_connections.

Однако стоит помнить, что при увеличении количества соединений с использованием параметра max_client_conn может потребоваться приведение в соответствие лимитов файловых дескрипторов в операционной системе.

Рекомендации по настройке ограничений на количество соединений приведены в документации.

Значения большей части рассмотренных параметров может быть переопределено для каждой базы данных в отдельности в разделе [databases], например:

[databases]
some_db = host=localhost port=5432 pool_size=50 min_pool_size=30 reserve_pool_size=10

Аналогично часть параметров может быть переопределена для каждой отдельно роли в разделе [users].

Аутентификация в Pangolin Pooler​

Базовый механизм аутентификации​

Поскольку пулер соединений является посредником между клиентами и экземплярами сервера, он должен уметь аутентифицировать подключающихся клиентов и себя при открытии соединений с экземпляром сервера.

При этом, так как для клиентов пулер имитирует экземпляр сервера, то и методы их аутентификации по большей части совпадают с методами, применяемыми на сервере Pangolin.

Метод аутентификации клиентов задается в параметре auth_type, значением которого в том числе может быть:

  • cert — аутентификация с использованием сертификата SSL
  • md5 — парольная аутентификация на основе алгоритма md5
  • scram-sha-256 — парольная аутентификация на основе алгоритма scram-sha-256
  • trust — без аутентификации
  • hba — для определения метода используется конфигурационный файл, заданный в параметре auth_hba_conf. Формат файла аналогичен файлу pg_hba.conf, используемому для определения метода аутентификации на сервере Pangolin

Пароли (или хеши) при использовании соответствующих методов аутентификации могут быть получены либо из файла userlist.txt (задается параметром auth_file), либо путем обращения к системному каталогу pg_authid в базе данных.

Например, содержимое файла userlist.txt может выглядеть следующим образом:

"some_user" "md5175c641eaed0b6c05ae8444b73d789f0"
"student" "SCRAM-SHA-256$4096:RAf9uYFejQCwQMS3kdGi8w==$2VQIEDmjVOek2V6i+ih2EArRAsmI2CJjMnDgaLELenw=:663yu3xX983xvgwI2+Ga/jIOllslzwF0xEV09fRl1J4="

Аутентификация клиентов в этом случае выполняется на основе информации из указанного файла.

Помимо этого, файл userlist.txt используется для получения пароля (или его хеша) для аутентификации при открытии соединения с экземпляром сервера, если он не был указан в строке подключения.

Однако такой способ возможен только для паролей, хранимых в открытом виде или в виде хешей md5. Хеши scram не могут использоваться при прохождении процедуры аутентификации из-за повышенных свойств безопасности алгоритма scram-sha-256.

Владельцем файла userlist.txt должен быть пользователь, с правами которого запускается Pangolin Pooler. Права на указанный файл также соответствующим образом должны быть ограничены.

Для получения пароля из системного каталога pg_authid требуется в параметре auth_query указать соответствующий SQL-запрос. Значение auth_query по умолчанию выглядит следующим образом:

SELECT rolname, CASE WHEN rolvaliduntil < now() THEN NULL ELSE rolpassword END FROM pg_authid WHERE rolname=$1 AND rolcanlogin

В качестве параметра ($1) подставляется имя роли, для которой требуется пароль или хеш. Запрос выполняется для всех пользователей, не указанных в файле userlist.txt от имени пользователя, указанного в параметре auth_user.

При этом для доступа к таблице pg_authid требуются права суперпользователя. Поэтому рекомендуется обернуть запрос к таблице pg_authid в функцию с правами создателя (SECURITY DEFINER) и выполнять ее от имени пользователя, не являющегося суперпользователем.

Механизм сквозной аутентификации​

В Pangolin Pooler в дополнение к базовому механизму аутентификации, реализованному в PgBouncer, имеется механизм сквозной аутентификации.

Данный механизм предполагает выполнение аутентификации клиентов исключительно на стороне экземпляра Pangolin.

Это позволяет:

  • Снизить накладные расходы, связанные с аутентификацией
  • Повысить уровень безопасности, в том числе из-за отсутствия необходимости хранения паролей в userlist.txt
  • Не следить за синхронизацией информации в именах пользователей и их паролях
  • Проводить аутентификацию любыми способами, поддерживаемыми экземпляром Pangolin (в том числе LDAP)
  • Проводить аудирование действий пользователей на уровне экземпляра

Включение указанного механизма осуществляется с использованием параметра auth_proxy (по умолчанию off).

Для этого Pangolin предоставляет отдельный сервис аутентификации, работающий на специальном порту, значение которого указывается в параметре auth_port (по умолчанию 5544).

Более подробно о механизме сквозной аутентификации можно узнать из документации.

Управление и мониторинг в Pangolin Pooler​

Для управления и мониторинга в Pangolin Pooler предусмотрена специальная консоль, доступ к которой можно получить, подключившись в psql к виртуальной базе данных pgbouncer.

Подключиться к ней могут пользователи, указанные в параметре admin_users (для полного доступа к командам консоли) или stats_users (для доступа только к командам мониторинга).

Например, если admin_users = student, то доступ к консоли может быть получен следующей командой:

[student@ServerName ~]$ psql -d pgbouncer -U student -p 6432

Консоль предоставляет следующие основные возможности:

  • Мониторинг состояния и накопленной статистики — команды серии SHOW
  • Управление соединениями пулера, в том числе следующие команды:
    • PAUSE — приостановка обслуживания клиентов
    • RESUME — возобновление обслуживания клиентов
    • SET — установка значения для параметра в файле конфигурации
    • RELOAD — перечитывание параметров из файла конфигурации

Для мониторинга предназначены команды серии SHOW. Например, состояние каждого из имеющихся пулов соединений можно узнать командой SHOW POOLS, информацию о подключенных клиентах — командой SHOW CLIENTS, а общую статистику использования пулов соединений — командой SHOW STATS.

Из команд управления можно выделить пару команд PAUSE и RESUME, с помощью которых можно приостановить обслуживание клиентов, например с целью перезагрузки экземпляра сервера. Это может потребоваться для применения значений параметров, требующих перезагрузки, или для обновления сервера.

При этом для клиентов разрыва соединения с пулером не происходит. Приостановка для них выглядит как непродолжительное зависание при выполнении запроса.

Полный перечень команд приведен в документации.

Итоги​

  • Большое количество соединений негативно сказывается на производительности экземпляра сервера
  • Пулер соединений обеспечивает совместное использование клиентами небольшого количества долгоживущих соединений
  • В Pangolin имеется собственный пулер соединений под названием Pangolin Pooler, основанный на PgBouncer
  • Режим транзакций пула имеет ряд ограничений, которые необходимо учитывать при разработке

Самопроверка​

Вопрос 1

Какие проблемы производительности могут возникать при большом количестве клиентских соединений? Выберите все верные варианты ответа:

Вопрос 2

Сколько режимов пулинга предусмотрено в Pangolin Pooler?

Вопрос 3

Для решения каких задач предназначен файл userlist.txt? Выберите все верные варианты ответа:

Вопрос 4

Какая функциональность Pangolin может некорректно работать при использовании Pangolin Pooler в режиме пула транзакций? Выберите все верные варианты ответа: