Site icon 8HOST.COM

Балансировка нагрузки MySQL при помощи HAProxy

HAProxy – это открытый балансировщик нагрузки для серверов HTTP и TCP.

В предыдущей статье данной серии рассказывается о настройке балансировки нагрузки HTTP при помощи HAProxy.

Данное руководство поможет настроить балансировку нагрузки сервера MySQL.

Примечание: На всех серверах MySQL должна быть настроена репликация по типу Master-Master, так как балансировка нагрузки включает в себя чтение и запись всех бэкендов.

Требования

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

Сервер 1 – балансировщик нагрузки

Сервер 2 – нод 1

Сервер 2 – нод 2

Запустите все серверы MySQL и и убедитесь в том, что репликация выполняется правильно.

1: Подготовка серверов MySQL

Сначала нужно подготовить серверы MySQL. Создайте две дополнительные учётные записи для HAProxy. Первый пользователь нужен для проверки состояния сервера:

root@mysql-1# mysql -u root -p -e "INSERT INTO mysql.user (Host,User) values ('10.0.0.100','haproxy_check'); FLUSH PRIVILEGES;"

Для доступа к кластеру MySQL при помощи HAProxy пользователь MySQL должен иметь права root. Стандартный пользователь root может входить только локально. Конечно, можно просто расширить привилегии root-пользователя; однако для таких случаев рекомендуется создать отдельного пользователя с привилегиями root.

root@mysql-1# mysql -u root -p -e "GRANT ALL PRIVILEGES ON *.* TO 'haproxy_root'@'10.0.0.100' IDENTIFIED BY 'password' WITH GRANT OPTION; FLUSH PRIVILEGES"

Примечание: Вместо haproxy_root и password укажите имя пользователя и надёжный пароль.

Достаточно выполнить эти действия на одном сервере MySQL – благодаря заранее настроенной репликации изменения будут дублированы на остальные серверы.

2: Установка клиента MySQL

Клиент MySQL нужно установить на сервер 1 (балансировщик нагрузки).

root@haproxy# apt-get install mysql-client

Попробуйте выполнить запрос на одном из master-серверов как пользователь haproxy_root:

root@haproxy# mysql -h 10.0.0.1 -u haproxy_root -p -e "SHOW DATABASES"

На экране должен появиться список БД  MySQL.

3: Установка HAProxy

На сервер 1 установите пакеты HAProxy:

root@haproxy# apt-get install haproxy

После установки нужно включить HAProxy, чтобы балансировщик мог запускаться при помощи скрипта инициализации:

root@haproxy# sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/haproxy

Чтобы убедиться, что настройка прошла успешно, запустите init-скрипт HAProxy без параметров:

root@haproxy:~# service haproxy
Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}

4: Настройка HAProxy

Переименуйте стандартный конфигурационный файл и создайте собственный файл.

mv /etc/haproxy/haproxy.cfg{,.original}
nano /etc/haproxy/haproxy.cfg

Первый блок конфигураций содержит глобальные и стандартные настройки:

global
log 127.0.0.1 local0 notice
user haproxy
group haproxy
defaults
log global
retries 2
timeout connect 3000
timeout server 5000
timeout client 5000

Подробнее об этих параметрах можно прочитать в предыдущей статье. Согласно данным настройкам HAProxy будет слушать сообщения для логов на 127.0.0.1; о том, как настроить rsyslog для прослушивания этого адреса, можно прочесть в разделе «Логирование».

Главный блок конфигураций выглядит так:

listen mysql-cluster
bind 127.0.0.1:3306
mode tcp
option mysql-check user haproxy_check
balance roundrobin
server mysql-1 10.0.0.1:3306 check
server mysql-2 10.0.0.2:3306 check

HAProxy не имеет специального «режима» для MySQL (в отличие от HTTP), потому нужно использовать tcp. Нужно настроить HAProxy для прослушивания адреса замыкания, если приложение находится на том же сервере; однако, если приложение находится на другом сервере, балансировщик HAProxy должен прослушивать 0.0.0.0 или внутренний IP-адрес.

Добавьте ещё один блок кода, чтобы настроить статистику распределения нагрузки

Примечание: Это совершенно необязательно; пропустите этот блок, если вам не нужна статистика.

listen 0.0.0.0:8080
mode http
stats enable
stats uri /
stats realm Strictly\ Private
stats auth A_Username:YourPassword
stats auth Another_User:passwd

Примечание: Укажите в коде свои имена пользователей и пароли.

Этот код настроит HAProxy для прослушивания HTTP-запросов на порт 8080, а статистические данные будут защищены базовой аутентификацией HTTP. Получить доступ к статистике можно по ссылке:

http://<Public IP of Load Balancer>:8080/

Завершив настройку, запустите HAProxy.

service haproxy start

Используйте клиент mysql для запроса HAProxy.

root@haproxy# mysql -h 127.0.0.1 -u haproxy_root -p -e "SHOW DATABASES"

Опция –h должна присутствовать в строке IP-адреса обратной связи; если её пропустить или указать localhost, клиент MySQL подключится к файлу mysql.sock, что приведёт к сбою.

5: Тестирование балансировки нагрузки и отказоустойчивости

Чтобы проверить балансировку нагрузки, запросите переменную server_id минимум дважды.

root@haproxy# mysql -h 127.0.0.1 -u haproxy_root -p -e "show variables like 'server_id'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |
+---------------+-------+
root@haproxy# mysql -h 127.0.0.1 -u haproxy_root -p -e "show variables like 'server_id'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+

Этот вывод говорит о балансировке нагрузки по алгоритму roundrobin с одинаковым весом. Измените вес mysql-2 и проверьте результат.

nano /etc/haproxy/haproxy.cfg
server mysql-2 10.0.0.2:3306 check weight 2

Перезапустите haproxy, чтобы обновить настройки.

service haproxy reload

Запросите server_id несколько раз:

root@haproxy:~# for i in `seq 1 6`
do
mysql -h 127.0.0.1 -u haproxy_root -ppassword -e "show variables like 'server_id'"
done
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+

Теперь балансировка нагрузки выполняется в соотношении 1: 2, где одна треть запросов отправляется на сервер mysql-1, а две трети – на mysql-2.

Остановите сервер MySQL, отключив сервис:

root@mysql-1# service mysql stop

или интерфейс:

root@mysql-1# ifconfig eth1 down

Запросите переменную show variables; следующие записи лога сообщат, когда и как HAProxy обнаружил сбой.

tail /var/log/haproxy/haproxy.log
Nov 15 00:08:51 localhost haproxy[1671]: Server mysql-cluster/mysql-1 is DOWN, reason: Layer4 timeout, check duration: 2002ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.

6: Настройка отказоустойчивости

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

Сначала нужно научиться измерять эту величину. Одним из способов является блокировка порта MySQL с помощью IPTables в течение определенного времени; позже можно удалить правило и проверить лог.

root@mysql-1:~# ifconfig eth1 down &&
date &&
sleep 20 &&
ifconfig eth1 up &&
date
Fri Nov 15 00:37:09 IST 2013
Fri Nov 15 00:37:29 IST 2013

Порт 3306 был заблокирован на 20 секунд. Теперь нужно проверить лог:

root@haproxy:~# tail /var/log/haproxy.log
Nov 15 16:49:38 localhost haproxy[1275]: Server mysql-cluster/mysql-1 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Nov 15 16:49:56 localhost haproxy[1275]: Server mysql-cluster/mysql-1 is UP, reason: Layer7 check passed, code: 0, info: "5.5.31-0+wheezy1-log", check duration: 1ms. 2 active and 0 backup servers online. 0 sessions requeued, 0 total in queue.

Как видно из полученных данных, на  обнаружение отказа ушло 6 секунд (16:49:32 – 16:49:38), а на его устранение – 4 секунды (16:49:52 – 16:49:56).

Это определяется параметрами rise, fall и inter.

Параметр rise устанавливает количество проверок, которые должен пройти сервер, чтобы получить статус operational (по умолчанию это 2).

Параметр fall определяет количество проверок, которые должен пройти сервер, чтобы получить статус dead (по умолчанию – 3).

Параметр inter определяет интервал между этими проверками (по умолчанию – 2000 миллисекунд).

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

16:49:32 - Port 3306 on mysql-1 was blocked
16:49:34 - Check - Failed - Failure No. 1
16:49:36 - Check - Failed - Failure No. 2
16:49:38 - Check - Failed - Failure No. 3 (server removed and event logged)

После удаления правила брандмауэра:

16:49:52 - Firewall rule removed port 3306 accessible
16:49:54 - Check - Passed - Success No. 1
16:49:56 - Check - Passed - Success No. 2 (server added to cluster and event logged)

Следующие настройки уменьшат интервал между проверками до 1 секунды, а также уменьшат количество проверок fall.

nano /etc/haproxy/haproxy.cfg
server mysql-1 10.0.0.1:3306 check fall 2 inter 1000
server mysql-2 10.0.0.2:3306 check fall 2 inter 1000

При большом количестве серверов MySQL не рекомендуется засорять частную сеть тестовыми пакетами. В таком случае используются параметры fastinter и downinter.

Параметр fastinter устанавливает интервал между проверками, в то время как сервер переходит из одного состояния в другое (включается или отключается).

Параметр downinter устанавливает интервал между проверками, когда сервер выключен.

Рассмотрим такой пример.

nano /etc/haproxy/haproxy.cfg
server mysql-1 10.0.0.1:3306 check fastinter 1000
server mysql-2 10.0.0.2:3306 check fastinter 1000

По умолчанию параметр inter имеет значение 2000 мс. Перезапустите HAProxy при такой конфигурации и повторите проверку:

root@mysql-1:~# iptables -A INPUT -p tcp --dport 3306 -j REJECT &&
date &&
sleep 20 &&
iptables -D INPUT -p tcp --dport 3306 -j REJECT &&
date
Fri Nov 15 17:18:48 IST 2013
Fri Nov 15 17:19:08 IST 2013

Проверьте лог HAProxy:

root@haproxy:~# tail /var/log/haproxy.log
Nov 15 17:18:52 localhost haproxy[1353]: Server mysql-cluster/mysql-1 is DOWN, reason: Layer4 connection problem, info: "Connection refused", check duration: 0ms. 1 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
Nov 15 17:19:11 localhost haproxy[1353]: Server mysql-cluster/mysql-1 is UP, reason: Layer7 check passed, code: 0, info: "5.5.31-0+wheezy1-log", check duration: 1ms. 2 active and 0 backup servers online. 0 sessions requeued, 0 total in queue.

Теперь на обнаружение сбоя уходит всего 4 секунды, а на восстановление сервера – 3 секунды.

В данном примере случилось следующее:

17:18:48 - Port 3306 blocked
17:18:50 - Check - Failed - Failure No. 1
17:18:51 - Check - Failed - Failure No. 2
17:18:52 - Check - Failed - Failure No. 3 (server removed and event logged)

После удаления правила брандмауэра:

17:19:08 - Firewall rule removed
17:19:10 - Check - Passed - Success No. 1
17:19:11 - Check - Passed - Success No. 2 (server added to cluster and event logged)

Обратите внимание, что интервал между блокированием сервера и первой проверкой составляет 2 секунды (интервал inter). Интервал между Test 1-Test 2 и Test 2-Test 3 – всего одна секунда (интервал fastinter). Такие же интервалы наблюдаются и во время включения сервера. Параметр fastinter управляет интервалом между проверками.

Что же делает downinter? После отключения сервера HAProxy продолжал проверять его каждые 2 секунды (интервал inter). Если вам кажется, что вы попусту тратите сетевые ресурсы, попробуйте изменить значение downinter на 5000, после чего HAProxy будет проверять отключенный сервер каждые 5 секунд.

Важно!

Выполненные ранее тесты отклонили пакеты (REJECT), а это значит, что HAProxy инициировал соединение, отправив серверу mysql-1 пакет SYN, и получил в ответ пакет RST (вместо SYN + ACK). Потому в логе появилась запись Connection refused. В таком случае нужно использовать только параметры fall, inter и fastinter.

Если же HAProxy не получает ничего после отправки пакета SYN, время соединения истекает. В таком случае вместе с fall, inter и fastinter нужно использовать параметр timeout. Это случается, если:

Примечание: Официальную документацию можно найти здесь.