如何使用HAProxy设置MySQL负载平衡
序幕
HAProxy 是一个开源软件,可以对 HTTP 和 TCP 服务器进行负载平衡。 在 上一篇关于 HAProxy 的文章中,我们为 HTTP 配置了负载平衡,在这篇文章中,我们将为 MySQL 做同样的事情。 您的所有 MySQL 服务器都必须配置为执行 Master-Master 复制,因为负载平衡涉及对所有后端的读取和写入。
本文将使用以下三个液滴:
Droplet 1 - 负载均衡器 主机名:haproxy 操作系统:Ubuntu 私有 IP:10.0.0.100
Droplet 2 - 节点 1 主机名:mysql-1 操作系统:Debian 7 私有 IP:10.0.0.1
Droplet 2 - 节点 2 主机名:mysql-2 操作系统:Debian 7 私有 IP:10.0.0.2
在继续之前,请确保所有 MySQL 服务器都已启动、运行并且正在正确复制数据库写入。
准备 MySQL 服务器
我们需要通过为 HAProxy 创建两个额外的用户来准备 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;"
从 HAProxy 访问 MySQL 集群时,需要具有 root 权限的 MySQL 用户。 所有服务器上的默认 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 主服务器上执行这些查询就足够了,因为更改会复制到其他服务器。
安装 MySQL 客户端
MySQL 客户端必须安装在 HAProxy droplet 上以测试连接性。
root@haproxy# apt-get install mysql-client
现在尝试以 haproxy_root 用户身份在其中一个主服务器上执行查询。
root@haproxy# mysql -h 10.0.0.1 -u haproxy_root -p -e "SHOW DATABASES"
这应该显示 MySQL 数据库的列表。
安装 HAProxy
在 HAProxy 服务器上安装包。
root@haproxy# apt-get install haproxy
启用由初始化脚本启动的 HAProxy。
root@haproxy# sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/haproxy
要检查此更改是否正确执行,请执行不带任何参数的 HAProxy 的初始化脚本。
root@haproxy:~# service haproxy Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}
配置 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 来监听它。 这也已在 同一篇文章 下的 为 HAProxy 配置日志记录中进行了介绍。
转到主要配置部分。
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
与 HTTP 负载平衡不同,HAProxy 没有针对 MySQL 的特定“模式”,因此我们使用 tcp。 我们已将 HAProxy 设置为仅侦听环回地址(假设应用程序位于同一服务器上),但是如果您的应用程序驻留在不同的 droplet 上,请使其侦听 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
替换“stats auth”中的用户名和密码。 这将使 HAProxy 在 端口 8080 上侦听 HTTP 请求,并且统计信息将受到 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 文件。
测试负载平衡和故障转移
要检查负载平衡是否有效,请查询 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
重新加载以应用此更改。
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
现在尝试“显示变量”查询以查看结果。 以下日志条目将指示 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.
减少故障转移间隔
当 MySQL 服务器出现故障时,HAProxy 需要一些时间来检测此故障并将其从集群中删除。 在本节中,我们将看到如何控制这个时间。 首先,我们将了解如何衡量这个值。 一种方法是使用 iptables 阻塞 MySQL 端口一段时间,然后删除规则并检查日志。
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:38 和 16:49:32 之间的差异),检测可以访问服务器需要 4 秒(16:49:56 和 16:49:52 之间的差异)。 这是由服务器参数上升、下降和区间决定的。
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 秒,同时也会减少跌倒测试的次数。
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”参数,它默认为 2000ms。 使用此配置,我们将重新启动 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 秒(与之前的 6 秒相比)即可检测到故障,并且只需 3 秒(与 4 秒相比)即可检测到服务器已启动。 这就是幕后发生的事情。
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)
首先注意端口阻塞事件(17:18:48)和第一次检查(17:18:50)之间的间隔,它是2秒(“inter”间隔)。 然后注意测试 1 <-> 测试 2 和测试 2 <-> 测试 3 之间的间隔,它只有 1 秒(“fastinter”间隔)。 当服务器从 DOWN 移动到 UP 时,可以注意到相同的时间间隔。 所以“fastinter”控制这些检查之间的间隔。
那么什么是downinter? 当服务器被声明为 DOWN 时,HAProxy 会继续每 2 秒检查一次(或中间提到的间隔)。 如果你觉得你正在使用不必要的网络资源,将 downinter 设置为 5000 将使 HAProxy 在 5 秒内仅检查一次 DOWN 服务器。
重要的
我们之前所做的测试拒绝了数据包,这意味着当 HAProxy 通过向 mysql-1 发送 SYN 数据包来启动连接时,它收到了一个 RST 数据包(而不是 SYN + ACK)。 这就是日志条目提到“连接被拒绝”的原因。 在这种情况下,只有 fall、inter 和 fastinter 值进入场景。
相反,如果 HAProxy 在发送 SYN 后没有收到任何内容,则连接超时。 在这种情况下,除了上述参数之外,“超时”持续时间也会出现。 如果发生这种情况
- iptables 设置为 DROP
- 私有接口已关闭
- 专用网络基础设施存在问题
延伸阅读
官方文档【X23X】http://cbonte.github.io/haproxy-dconv/configuration-1.4.html【X87X】