Асинхронный пул соединений QCP

Асинхронный пул соединений (Quantum Connection Pool, QCP) обеспечивает подключение и поддержку связи с удаленными клиентами.



Общий принцип работы

QCP принимает входящие подключения от удаленных клиентов по адресу, указанному в listening_address (по умолчанию — 0.0.0.0:8080), и и перенаправляет их трафик серверам баз данных, перечисленных в разделе servers. Соединения с серверами устанавливаются (и завершаются) автоматически, по мере необходимости.

В зависимости от режима работы, задаваемого параметром relay_mode, перенаправление трафика данных от клиентов к серверам осуществляется одним из следующих способов:

  1. relay_mode: Session: при первом обращении к серверу клиенту выделяется уникальное соединение с базой данных, которое возвращается в пул только при отключении клиента.
  2. 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.