Асинхронный пул соединений QCP
Асинхронный пул соединений (Quantum Connection Pool, QCP) обеспечивает подключение и поддержку связи с удаленными клиентами.
Общий принцип работы
QCP принимает входящие подключения от удаленных клиентов по адресу, указанному в listening_address (по умолчанию — 0.0.0.0:8080), и и перенаправляет их трафик серверам баз данных, перечисленных в разделе servers. Соединения с серверами устанавливаются (и завершаются) автоматически, по мере необходимости.
В зависимости от режима работы, задаваемого параметром relay_mode, перенаправление трафика данных от клиентов к серверам осуществляется одним из следующих способов:
- relay_mode: Session: при первом обращении к серверу клиенту выделяется уникальное соединение с базой данных, которое возвращается в пул только при отключении клиента.
- relay_mode: Smart: при обращении к серверу клиенту выделяется уникальное соединение с базой данных, которое возвращается в пул тогда и только тогда, когда в ответе от сервера будет стоять флаг Idle (см. раздел Форматы сообщений, сообщение ReadyForQuery).
С полным описанием настроек можно ознакомиться в примере конфигурационного файла qcp/config-example.yaml.
Запуск и работа
Запуск осуществляется с помощью утилиты qcp (qcp --help
для списка
параметров), остановка — утилитой qcp-ctrl (qcp-ctrl --help
для списка
параметров). Например, чтобы остановить запущенный экземпляр QCP, необходимо
выполнить команду qcp-ctrl quit
.
Вывод записей журнала в процессе работы QCP контролируется параметром log_output (см. qcp/config-example.yaml), при этом уровень протоколирования задается параметром log_level (подробнее про уровни протоколирования см. на справочной странице LevelFilter на соответствующем сайте). Например, чтобы выводить записи журнала уровня Info и выше в файл /tmp/qcp.log, необходимо задать следующие параметры в файле конфигурации:
log_level: Info
log_output:
file: /tmp/qcp.log
Потребление памяти
При запуске программы единовременно выделяется количество памяти, указанное в разделе arena файла конфигурации:
# Конфигурация памяти (необязательно)
arena:
chunk_size: 65 KB # Размер одного блока памяти; поддерживаются суффиксы B, KB, MB, GB
# Общее количество потребляемой памяти можно указать, либо используя параметр
# «количество блоков памяти»:
chunks_count: 3150 # Количество таких блоков
# либо указав общее количество напрямую:
total_size: 3.1 GB # Поддерживаются суффиксы B, KB, MB, GB
Подключение к СУБД
QCP может подключаться либо к одиночному серверу СУБД, либо к кластеру СУБД, управляемому Patroni.
Для подключения к серверу СУБД в разделе server: необходимо указать его адрес, например:
server:
# Одиночный сервер
address: # Тип и адрес подключения (TCP или сокет домена Unix)
Tcp: "127.0.0.1:1234"
# Unix: "/home/mexus/devel/optim/qhb-with-rust/build/dbsockets/.s.PGSQL.5432"
Для подключения к кластеру СУБД, управляемому Patroni:
server:
# Кластер Patroni
patroni:
# Сервера (узлы) из кластера
nodes:
- dbms_address: # Адрес СУБД
Tcp: "127.0.0.1:1234"
rest_url: "http://127.0.0.1:8090" # URL REST API patroni
- dbms_address: # Адрес СУБД
Unix: "/путь/к/сокету/unix"
rest_url: "http://127.0.0.2:8090" # URL REST API patroni
cluster_name: my_cluster # Имя кластера (используется как префикс для метрик).
single_try_timeout: 5 sec # Необязательный параметр: максимальное ограничение времени на
# одну попытку узнать, какой из серверов кластера мастер.
master_check_interval: 1500 ms # Необязательный параметр: как часто
# опрашивать кластер. По умолчанию — 1500
# миллисекунд.
Необходимо перечислить список всех узлов кластера, указывая адрес СУБД и адрес REST API Patroni для каждого узла. Так же необходимо задать имя кластера с помощью параметра cluster_name.
При таком подключении QCP будет регулярно опрашивать Patroni на всех узлах с целью определения текущего мастера. Если мастер изменяется, то QCP прерывает все текущие запросы от подключенных клиентов и подключается к новому мастеру.
Также можно указать дополнительные параметры:
- single_try_timeout: ограничение по времени на каждый REST запрос,
- master_check_interval: как часто опрашивать кластер с целью определения текущего мастера.
Независимо от того, осуществляется ли подключение к кластеру или к одной СУБД, для описания подключений используются следующие необязательные параметры:
- inactive_timeout: временной интервал, после которого неактивное соединение с сервером будет закрыто при условии наличия минимального количества подключений.
- lifetime: примерное максимальное время жизни соединения к серверу, по истечении которого оно будет закрыто.
- heart_beat_interval: интервал проверки допустимости соединения с сервером в период, когда подключение не ассоциировано ни с одним клиентом.
Многопользовательский режим
QCP поддерживает возможность подключения к кластеру СУБД, используя различные пары пользователь-БД.
Для каждой из таких пар создается отдельный пул подключений. Когда клиент подключается к QCP, он указывает логин пользователя и имя БД, и, в соответствии с этими параметрами, QCP помещает его в нужный пул.
При попытке подключения к QCP с парой пользователь-БД, которая отсутствует в конфигурации, клиент получит ошибку:
FATAL: Unknown user name, database name, or invalid combination of user and database
-- КРИТИЧНО: Неизвестное имя пользователя, имя базы данных или недопустимое
-- сочетание пользователя и базы данных
При этом в логах QCP появится примерно следующее сообщение:
[qcp::relay_helper] [WARN] Client ... startup sequence failed: Unknown user-database pair: user "user", db "db"
-- (сбой в последовательности запуска: неизвестная пара пользователь-БД:
-- пользователь "user", БД "db")
Пары пользователь-БД перечисляются в секции connections: раздела server:, например:
# Первый пул подключений.
- username: user # Имя пользователя
password: something # Необязательный параметр: пароль для аутентификации
database: utilities # Необязательный параметр: имя базы данных.
# Если не указана, в качестве имени базы будет
# использоваться имя пользователя.
backends: # Количество подключений с данным именем пользователя и базой
initial: 1 # .. при старте пула
min: 1 # .. минимальное
max: 3 # .. максимальное
# Необязательная секция. Описывает то, как клиент должен быть
# аутентифицирован на QCP. Если секция не задана, то для авторизации
# пользователя с данным именем пользователя для данной базы на QCP будет
# использоваться тот же пароль, какой задан для сервера, если он задан.
client_auth:
# Метод аутентификации: trust или md5.
method: md5
# Пароль для авторизации. Если не задан, будет использоваться тот
# же, что и для подключения QCP к базе.
password: lol2
options: # Необязательный параметр: дополнительные параметры подключения,
# передаваемые базе данных
option_name: option_value
# Второй пул подключений.
- username: qhb # Имя пользователя
backends: # Количество подключений с данным именем пользователя и базой
initial: 2 # .. при старте пула
min: 2 # .. минимальное
max: 5 # .. максимальное
Для описания каждого пула подключений для пары пользователь-БД требуется указать имя пользователя (username) и имя БД (database). Поле database можно пропустить, тогда оно примет то же значение, что и username.
Помимо этого, необходимо указать ограничения на количество подключений к СУБД в данном пуле, в секции backends::
- initial указывает, сколько будет открыто подключений к СУБД с данной парой пользователь-БД при старте QCP,
- min — ограничение на минимальное количество подключений к СУБД, может быть меньше, чем initial.
- max — максимальное количество подключений к СУБД. Должно быть не меньше, чем initial и min.
Если для подключения к СУБД с данными пользователем и БД требуется пароль, то его можно указать в поле password.
Так же доступна секция options:, позволяющая передать произвольные аргументы командной строки для сервера в виде имя: значение.
Авторизация клиентов на QCP
По умолчанию для каждой пары пользователь-БД для авторизации пользователей QCP использует такие же настройки, как и для авторизации QCP на СУБД: если СУБД требует пароль, то и QCP будет требовать от пользователя его же, если СУБД не требует пароль, то и QCP не будет.
Данное поведение можно переопределить, используя секцию client_auth::
- поле method позволяет переопределить метод авторизации,
- поле password позволяет задать пароль, отличный от пароля, используемого для подключения к СУБД.
Применение параметров без перезапуска QCP
Некоторые параметры конфигурации можно изменить, не перезапуская QCP. Такой способ называется «перезагрузка файла конфигурации».
Для этого необходимо изменить требуемые параметры в конфигурационном файле, после чего выполнить
sudo systemctl reload qcp
Если QCP работает не под управлением systemd, то необходимо определить
идентификатор процесса QCP (обратитесь к системному администратору, чтобы
узнать, как это сделать на вашей ОС), после чего выполнить следующую команду,
подставляя найденный идентификатор вместо ***
***:
sudo kill -USR1 <pid>
Для того чтобы обновленная конфигурация применилась, необходимо, чтобы конфигурационный файл был допустимым. В противном случае в логах QCP отобразится невозможность применения обновленной конфигурации, и QCP продолжит работать в прежнем режиме. Частичное применение конфигурации в таком случае исключено.
Если применение возможно, в логах появится соответствующая запись:
[INFO] Reloaded configuration file /путь/к/config.yaml
-- [ИНФОРМАЦИЯ] перезагружен файл конфигурации /путь/к/config.yaml
Обратите внимание, что для применения обновленной конфигурации требуется некоторое время, которое может достигать нескольких секунд при высокой нагрузке.
Применение параметров подключения для каждой пары пользователь-БД сопровождается записями в логе:
[INFO] Updating connection configuration for user "qhb", db "qhb"
[INFO] Applied new connection parameters for user "qhb", db "qhb"
-- [ИНФОРМАЦИЯ] Обновление конфигурации подключения для пользователя "qhb", БД "qhb"
-- [ИНФОРМАЦИЯ] Добавлены новые параметры подключения для пользователя "qhb", БД "qhb"
Применение параметров входящих подключений сопровождается записью в журнале:
[INFO] Incoming parameters updated
-- [ИНФОРМАЦИЯ] Обновлены параметры входящих подключений
Изменение следующих параметров не может быть осуществлено без перезапуска QCP, поэтому они будут проигнорированы QCP при перезагрузке файла конфигурации:
- arena
- log_level
- log_output
- log_colouring
- log_timestamps
- worker_threads
Следующие параметры будут обновлены во время следующего их использования:
- accept_clients_no_backends: параметр будет обновлен при подключении следующего клиента, либо же когда появится доступное подключение к СУБД, если прием новых подключений от клиентов был приостановлен.
- в секции servers_retry_back_off параметры min_wait, max_wait и max_wait_at будут обновлены при следующей попытке установить подключение к СУБД.
- в секции server параметры inactive_timeout, lifetime, check_interval и heart_beat_interval будут применены к подключениям к СУБД, установленным после перезагрузки файла конфигурации.
Изменение типа подключения к СУБД (одиночный сервер, кластер под управлением Patroni) приведет к отключению всех текущих клиентов и разрыву всех текущих подключений к СУБД.
Удаление подключения из секции connections: раздела server: приведет к отключению всех клиентов, использующих такие подключения, а также к разрыву всех таких подключений к СУБД.
Изменение имени пользователя (username), имени БД (database), пароля (password) или параметров командной строки сервера (options) у подключения приведет к отключению всех клиентов, использующих такие подключения, а также к разрыву всех таких подключений к СУБД и последующему переподключению к СУБД с обновленными параметрами.
Изменение поля client_auth у подключения будет применено для всех последующих подключений к QCP.