Настройка ProxySQL

Оглавление

Настройка репозиториев

Заглядываем в файл /etc/debian_version или /etc/lsb-release, определяем кодовое имя релиза.

Открываем страницу repo.percona.com/percona/apt/ и находим там пакет percona-release_latest.bionic_all.deb, где bionic - кодовое имя релиза. Копируем ссылку на пакет и скачиваем в систему, где нужно установить ProxySQL:

$ wget http://repo.percona.com/percona/apt/percona-release_latest.bullseye_all.deb

Установим пакет в систему:

# dpkg -i percona-release_latest.bullseye_all.deb

Подключаем репозитории с ProxySQL:

# percona-release enable proxysql

Обновляем список пакетов, доступных через репозитории:

# apt-get update

Установка

Устанавливаем необходимые пакеты:

# apt-get install proxysql2

Предварительная настройка

У ProxySQL многоуровневая система конфигураций, которая сильно запутывает работу с ним: есть используемая конфигурация, конфигурация в оперативной памяти, конфигурация в базе данных SQLite3 на диске и конфигурация из файла конфигурации /etc/proxysql.cnf. Для того, чтобы не запутаться во всём этом многообразии, я буду использовать только конфигурацию из файла конфигурации /etc/proxysql.cnf. К сожалению, при перезапуске ProxySQL конфигурация из базы данных имеет приоритет над конфигурацией из файла /etc/proxysql.cnf. Чтобы при перезапуске конфигурация всегда бралась из файла /etc/proxysql.cnf, я добавлю в service-файл дополнительную опцию --initial.

Кроме того, в конфигруации по умолчанию ProxySQL нужно указать пользователя MySQL, с помощью которого он будет проверять доступность СУБД. В моём случае сервер MySQL всего один и при его недоступности переводить нагрузку некуда, поэтому эта функциональность избыточна. Отключить проверки можно с помощью опции --no-monitor, которую тоже внесём в обновлённый service-файл.

Скопируем service-файл из пакета в каталог для собственных и изменённых service-файлов:

# cp /lib/systemd/system/proxysql.service /etc/systemd/system

Откроем файл /etc/systemd/system/proxysql.service в текстовом редакторе и отредактируем строчку с командой запуска ProxySQL следующим образом:

ExecStart=/usr/bin/proxysql --initial --no-monitor -c /etc/proxysql.cnf

Для того, чтобы информировать систему инициализации systemd об изменениях в service-файлах, вызовем команду:

# systemctl daemon-reload

Также мне не понравилось расположение журналов работы сервиса, настроенное по умолчанию. Журналы находятся в каталоге /var/lib/proxysql, а не в более привычном /var/log/proxysql. Исправим это.

Откроем в редакторе файл конфигурации /etc/proxysql.cnf и отредактируем строчку:

errorlog="/var/log/proxysql/proxysql.log"

Откроем в редакторе файл ротации журналов /etc/logrotate.d/proxysql-logrotate и поменяем путь к журналам в нём:

/var/log/proxysql/*.log {

Переместим сам журнал:

# mkdir /var/log/proxysql/
# chown proxysql:proxysql /var/log/proxysql/
# mv /var/lib/proxysql/proxysql.log /var/log/proxysql/

Настройка интерфейса администрирования

ProxySQL по умолчанию настраивается на прослушивание двух TCP-портов: 6032 и 6033. Первый порт используется для администрирования системы, а на втором принимаются подключения от клиентов. Номер порта 6033 соответствует номеру порта MySQL по умолчанию 3306, цифры которого переставлены в ообратном порядке. По умолчанию порт 6032 доступен со всех адресов и подключиться к нему можно с помощью логина "admin" и пароля "admin", что не очень безопасно.

Разрешим подключение только к локальному интерфейсу и зададим более сложный пароль, отредактировав секцию admin_variables в файле /etc/proxysql.cnf:

admin_variables=
{
    admin_credentials="root:p4$$w0rd"
    mysql_ifaces="127.0.0.1:6032"
}

Настройка проксирования

В секции mysql_variables я оставил нетронутыми все настройки, за исключением адреса, на котором принимаются входящие подключения, исключив приём подключений на Unix-сокете:

interfaces="0.0.0.0:6033"

В секции mysql_servers нужно настроить серверы MySQL, на которые будут проксироваться входящие подключения. В моём случае это только один локальный сервер, проксировать подключения будем только в Unix-сокет, а количество подключений к серверу ограничим двадцатью:

mysql_servers =
(
    {
        address = "/var/run/mysqld/mysqld.sock"
        port = 0
        hostgroup = 0
        max_connections = 20
    },
)

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

mysql_users =
(
    {
        username = "user"
        password = "p4$$w0rd"
        default_hostgroup = 0
        active = 1
        max_connections = 1500
        fast_forward = 1
    },
)

В опции password можно указать как сам пароль, так и его хэш-функцию, выдаваемую функцией PASSWORD() из MySQL. Для получения хэша можно воспользоваться запросом такого вида:

SELECT PASSWORD('p4$$w0rd');

Стоит обратить внимание на опции hostgroup и default_hostgroup у серверов и клиентов. Они определяют соответствие между клиентами и серверами, так что запросы от клиентов из определённой группы можно распределять между несколькими серверами MySQL той же группы, а клиенты и серверы из разных групп при этом будут оставаться изолированными друг от друга.

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

Изменение конфигурации без перезапуска

Для изменения конфигурации без перезапуска ProxySQL нужно отредактировать файл конфигурации /etc/proxysql.cnf и выполнить команды через интерфейс администрирования:

$ mysql -uroot -p -h127.0.0.1 -P6032 -e 'LOAD ADMIN VARIABLES TO RUNTIME; LOAD ADMIN VARIABLES FROM CONFIG; LOAD MYSQL VARIABLES TO RUNTIME; LOAD MYSQL VARIABLES FROM CONFIG; LOAD MYSQL SERVERS TO RUNTIME; LOAD MYSQL SERVERS FROM CONFIG; LOAD MYSQL USERS TO RUNTIME; LOAD MYSQL USERS FROM CONFIG; LOAD MYSQL QUERY RULES TO RUNTIME; LOAD MYSQL QUERY RULES FROM CONFIG; LOAD SCHEDULER TO RUNTIME; LOAD SCHEDULER FROM CONFIG;'

Для удобства можно доработать service-файл /etc/systemd/system/proxysql.service, в который прописать правило перезагрузки сервиса:

ExecReload=/usr/bin/mysql --defaults-file=/root/.my.cnf -h127.0.0.1 -P6032 -e 'LOAD ADMIN VARIABLES TO RUNTIME; LOAD ADMIN VARIABLES FROM CONFIG; LOAD MYSQL VARIABLES TO RUNTIME; LOAD MYSQL VARIABLES FROM CONFIG; LOAD MYSQL SERVERS TO RUNTIME; LOAD MYSQL SERVERS FROM CONFIG; LOAD MYSQL USERS TO RUNTIME; LOAD MYSQL USERS FROM CONFIG; LOAD MYSQL QUERY RULES TO RUNTIME; LOAD MYSQL QUERY RULES FROM CONFIG; LOAD SCHEDULER TO RUNTIME; LOAD SCHEDULER FROM CONFIG;'

Для применения нового service-файла нужно сообщить об этом systemd:

# systemctl daemon-reload

В строке перезагрузки упоминается файл /root/.proxysql.cnf с настройками клиента mysql. Создадим его:

[client]
user = root
password = p4$$w0rd
host = 127.0.0.1
port = 6032

Чтобы содержимое файла не увидели посторонние, выставим владельца, группу и права доступа:

# chown root:root /root/.proxysql.cnf
# chmod u=rw,go= /root/.proxysql.cnf

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

# systemctl reload proxysql

Тонкая настройка

Простаивающие потоки

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

Для того, чтобы включить использование дополнительных потоков, нужно отредактирвоать файл /etc/systemd/system/proxysql.service в текстовом редакторе и прописать в команду запуска ProxySQL опцию --idle-threads следующим образом:

ExecStart=/usr/bin/proxysql --initial --no-monitor --idle-threads -c /etc/proxysql.cnf

Для того, чтобы информировать систему инициализации systemd об изменениях в service-файлах, вызовем команду:

# systemctl daemon-reload

Для применения настроек необходимо перезапустить ProxySQL:

# systemctl restart proxysql

Настройки мультиплексирования подключений

При выполнении запросов INSERT или UPDATE сервер MySQL возвращает вместе с ответом последнее значение автоинкрементного поля, использованное при исполнении запроса. То же самое значение можно узнать с помощью функции LAST_INSERT_ID(). ProxySQL отключает простаивающие входящие подключения от подключений к серверу и при появлении активности может соединить входящее подключение с другим подключением к серверу MySQL, из-за чего функция LAST_INSERT_ID() может вернуть значение из другого подключения.

Для того, чтобы такие приложения продолжали работать корректно, ProxySQL отслеживает запросы INSERT или UPDATE во входящих подключениях и удерживает соответствие подключению к серверу на connection_delay_multiplex_ms миллисекунд (по умолчанию - 0) и действует на последующие auto_increment_delay_multiplex запросов (по умолчанию - 5), но не дольше, чем на auto_increment_delay_multiplex_timeout_ms (по умолчанию - 10000). Последняя опция была добавлена в ProxySQL версии 2.4.0.

Если приложение не использует функцию LAST_INSERT_ID(), то изменение настроек по умолчанию может существенно уменьшить использование подключений к серверу MySQL. Отключим удержание подключений, для чего добавим в секцию mysql_variables файла конфигурации /etc/proxysql.cnf следующие опции:

mysql_variables = 
{
    auto_increment_delay_multiplex=0
    connection_delay_multiplex_ms=0
    auto_increment_delay_multiplex_timeout_ms=0
}

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

Для применения настроек нужно выполнить команду:

# systemctl reload proxysql

Использованные материалы