本博客讨论HAProxy+PXC集群架构。
1.架构说明
单纯的PXC集群需要对外部应用程序暴露多个集群内部的MySQL节点的IP地址,才能让应用程序使用到多节点读写数据的便利,同时,PXC集群本身没有提供负载均衡的功能。
HAProxy+PXC集群架构中,引入负载均衡组件HAProxy,使得对外部应用只需要暴露HAProxy的外部地址和端口即可,而无需让应用程序直接使用MySQL节点自身的地址。
同时HAProxy提供了负载均衡的功能,可以平衡集群内各个MySQL节点的负载水平。
2.核心原理
DBA编写一个脚本程序,检测MySQL节点的可用状态,并且配置为xinetd下运行的http服务。HAProxy会自动访问这个http服务端口,从而取得MySQL节点的可用状态。在某个MySQL节点不可用时,应用程序访问HAProxy的对外服务端口时,HAProxy将不会将不可用节点参加负载均衡。在不使用HAProxy时,这个工作将需要应用程序来完成。
3.架构缺点
由于所有的流量都会通过HAProxy来转发,因此HAProxy节点自身容易成为潜在的单点故障节点。为了解决HAProxy自身的高可用问题,可以对HAProxy自身启用高可用方案,比如使用KeepAlived+HAProxy+PXC架构。这样将在多个节点上运行HAProxy,同时使用KeepAlived决定将VIP附加到哪个HAProxy节点上,这种方案彻底解决了HAProxy和PXC两个组成部分的高可用问题。
4.适用场景
在需要对若干MySQL服务节点进行负载均衡时可以使用HAProxy来搭建集群架构。还可以通过配置多个前端和后端的方式实现基于连接的MySQL读写分离架构。
5.搭建环境
主要步骤:
(1)下载并安装haproxy相关的包。
(2)创建haproxy的配置文件。
(3)实现pxc集群的节点检测功能。
(4)启动haproxy。
具体步骤如下:
(1).下载并安装haproxy相关的包。
主要需要安装haproxy软件包。
(2)创建haproxy的配置文件。
haproxy.cfg文件内容如下:
[[email protected] haproxy]# cat haproxy.cfg
global
log 127.0.0.1 local2
maxconn 65535
user haproxy
group haproxy
daemon
nbproc 3
defaults
log global
option tcplog
option dontlognull
retries 3
option redispatch
option abortonclose
timeout connect 10s
timeout client 10m
timeout server 10m
timeout queue 10m
frontend mysqlcluster-front
bind *:3320
mode tcp
default_backend mysqlcluster-back
frontend stats-front
bind *:80
mode http
default_backend stats-back
backend mysqlcluster-back
mode tcp
balance roundrobin
option httpchk
server 11.1.1.201 11.1.1.201:3306 check port 13306 inter 2000 rise 3 fall 3 weight 10
server 11.1.1.202 11.1.1.202:3306 check port 13306 inter 2000 rise 3 fall 3 weight 10
server 11.1.1.203 11.1.1.203:3306 check port 13306 inter 2000 rise 3 fall 3 weight 10
server 11.1.1.204 11.1.1.204:3306 check port 13306 inter 2000 rise 3 fall 3 weight 10
backend stats-back
mode http
stats uri /haproxy/stats
stats auth admin:123456
stats refresh 3s
前端:mysqlcluster-front,对应的后端为 mysqlcluster-back。
前端定义了haproxy对外提供服务的端口为3320,即mysql客户端将通过3320端口访问haproxy的前端,进而间接访问后端的真实MySQL服务中的一个,具体哪个由策略roundrobin决定。后端定义了真实MySQL服务的主机和端口列表,同时定义了每个主机的检测端口,检测方式是http方式,即需要每个主机提供一个基于http的网页,通过这个网页的结果取得MySQL服务的状态。
另外还定义了一个haproxy自己的监控前端和后端。提供了一个基于80端口的http服务站点。
haproxy的源码包中还提供了一个haproxy服务控制脚本。
[[email protected] haproxy]# cat haproxy
#!/bin/sh
#
# chkconfig: - 85 15
# description: HA-Proxy is a TCP/HTTP reverse proxy which is particularly suited \
# for high availability environments.
# processname: haproxy
# config: /etc/haproxy/haproxy.cfg
# pidfile: /var/run/haproxy.pid
# Script Author: Simon Matter <[email protected]>
# Version: 2004060600
# Source function library.
if [ -f /etc/init.d/functions ]; then
. /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
. /etc/rc.d/init.d/functions
else
exit 0
fi
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
#[ "${NETWORKING}" = "no" ] && exit 0
# This is our service name
BASENAME=`basename $0`
if [ -L $0 ]; then
BASENAME=`find $0 -name $BASENAME -printf %l`
BASENAME=`basename $BASENAME`
fi
BIN=/usr/local/sbin/$BASENAME
CFG=/etc/$BASENAME/$BASENAME.cfg
echo "CFG={${CFG}}"
[ -f $CFG ] || exit 1
echo "CFG found."
PIDFILE=/var/run/$BASENAME.pid
LOCKFILE=/var/lock/subsys/$BASENAME
RETVAL=0
start() {
quiet_check
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with ‘$BASENAME check‘."
return 1
fi
echo -n "Starting $BASENAME: "
daemon $BIN -D -f $CFG -p $PIDFILE
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $LOCKFILE
return $RETVAL
}
stop() {
echo -n "Shutting down $BASENAME: "
killproc $BASENAME -USR1
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
[ $RETVAL -eq 0 ] && rm -f $PIDFILE
return $RETVAL
}
restart() {
quiet_check
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with ‘$BASENAME check‘."
return 1
fi
stop
start
}
reload() {
if ! [ -s $PIDFILE ]; then
return 0
fi
quiet_check
if [ $? -ne 0 ]; then
echo "Errors found in configuration file, check it with ‘$BASENAME check‘."
return 1
fi
$BIN -D -f $CFG -p $PIDFILE -sf $(cat $PIDFILE)
}
check() {
$BIN -c -q -V -f $CFG
}
quiet_check() {
$BIN -c -q -f $CFG
}
rhstatus() {
status $BASENAME
}
condrestart() {
[ -e $LOCKFILE ] && restart || :
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
reload)
reload
;;
condrestart)
condrestart
;;
status)
rhstatus
;;
check)
check
;;
*)
echo $"Usage: $BASENAME {start|stop|restart|reload|condrestart|status|check}"
exit 1
esac
exit $?
(4).实现MySQL服务节点的检测功能。
haproxy通过MySQL服务节点提供的http网页来检测节点可用与否。因此,需要在每个节点中部署http服务,并且通过cgi脚本检测MySQL服务的可用与否。
本次采用xinetd来加载cgi脚本实现http服务。
首先需要安装xinetd服务。
yum install -y xinetd
然后编写一个http服务脚本,端口为haproxy.cfg中定义的13306。
[[email protected] haproxy]# cat /etc/xinetd.d/pxc_cluster_check
# default: on
# description: pxcclusterchk
service pxcclusterchk
{
# this is a config for xinetd, place it in /etc/xinetd.d/
disable = no
flags = REUSE
socket_type = stream
type = UNLISTED
port = 13306
wait = no
user = nobody
server = /opt/haproxy/pxcclusterchk
log_on_failure += USERID
only_from = 0.0.0.0/0
#
# Passing arguments to clustercheck
# <user> <pass> <available_when_donor=0|1> <log_file> <available_when_readonly=0|1> <defaults_extra_file>"
# Recommended: server_args = user pass 1 /var/log/log-file 0 /etc/my.cnf.local"
# Compatibility: server_args = user pass 1 /var/log/log-file 1 /etc/my.cnf.local"
# 55-to-56 upgrade: server_args = user pass 1 /var/log/log-file 0 /etc/my.cnf.extra"
#
# recommended to put the IPs that need
# to connect exclusively (security purposes)
per_source = UNLIMITED
}
当haproxy访问本节点的13306端口时xinetd会将脚本pxcclusterchk脚本的输出发送到haproxy。
再编写一个pxcclusterchk脚本:
[[email protected] haproxy]# cat pxcclusterchk
#!/bin/bash
MYSQL_CLIENT=/usr/bin/mysql
MYSQL_USER=pxc
MYSQL_PASSWORD=123456
WSREP_STATUS=`${MYSQL_CLIENT} --host=localhost --user=${MYSQL_USER} --password=${MYSQL_PASSWORD} -e "show status like ‘wsrep_local_state‘;" 2>/dev/null |awk ‘{if (NR!=1){print $2}}‘ 2>/dev/null`
if [ "${WSREP_STATUS}" == "4" ]
then
/bin/echo -e "HTTP/1.1 200 OK\r\n"
/bin/echo -e "Content-Type: text/plain\r\n"
/bin/echo -e "\r\n"
/bin/echo -e "PXC Cluster is running.\r\n"
/bin/echo -e "WSREP_STATUS:{${WSREP_STATUS}}.\r\n"
/bin/echo -e "\r\n"
else
/bin/echo -e "HTTP/1.1 503 Service Unavailable \r\n"
/bin/echo -e "Content-Type: text/plain\r\n"
/bin/echo -e "\r\n"
/bin/echo -e "PXC Cluster is down.\r\n"
/bin/echo -e "WSREP_STATUS:{${WSREP_STATUS}}.\r\n"
/bin/echo -e "\r\n"
fi
最后重新启动xinetd服务。
systemctl restart xinetd
这时可以使用curl检查13306端口的服务是否正常工作。
[[email protected] haproxy]# ps -elf|grep xinetd
1 S root 943 1 0 80 0 - 6791 poll_s 03:59 ? 00:00:00 /usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid
0 R root 8474 1712 0 80 0 - 28176 - 07:03 pts/0 00:00:00 grep --color=auto xinetd
[[email protected] haproxy]# curl http://11.1.1.201:13306
Content-Type: text/plain
PXC Cluster is running.
WSREP_STATUS:{4}.
curl: (56) Recv failure: Connection reset by peer
基本上可以满足haproxy的要求。
(4).启动haproxy服务。
执行:
./haproxy start
此时可以通过浏览器访问haproxy的监控页面:
目前配置的三个节点201,202,203均已正常在线(UP状态)。此图中显示的204这个节点暂时没有上线启动,因此状态为DOWN状态。
可以通过mysql客户端连接到haproxy的3320端口来测试负载均衡的节点分配情况。
[[email protected] bak]# mysql -upxc -p -h11.1.1.201 -P3320
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 96d42c3c-b9df-11e8-acbd-000c298fa201 |
+--------------------------------------+
1 row in set (0.00 sec)
mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 201 |
+-------------+
1 row in set (0.00 sec)
发现访问到的节点为201节点。
断开连接后重新连接3320端口:
mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 202 |
+-------------+
1 row in set (0.01 sec)
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 0fbb6a69-b9fc-11e8-ae6e-000c2997a175 |
+--------------------------------------+
1 row in set (0.01 sec)
发现实际访问的节点为202节点。
至此,HAProxy+MySQL PXC集群架构搭建完毕。
6.故障转移
在PXC集群3个节点在线的情况下,通过mysql客户端访问haproxy的3320端口。
[[email protected] bak]# mysql -upxc -p -h11.1.1.201 -P3320
mysql> select @@server_uuid,@@server_id;
+--------------------------------------+-------------+
| @@server_uuid | @@server_id |
+--------------------------------------+-------------+
| 0fbb6a69-b9fc-11e8-ae6e-000c2997a175 | 202 |
+--------------------------------------+-------------+
1 row in set (0.00 sec)
此时实际上间接访问的是202节点的MySQL服务。
现在关闭掉202节点的MySQL服务。通过haproxy的监控页面确认202节点的MySQL服务已下线停止。
在不退出mysql客户端的情况下,继续执行SQL语句。
mysql> select @@server_uuid,@@server_id;
ERROR 2013 (HY000): Lost connection to MySQL server during query
此时mysql客户端报错提示已经丢失了到MySQL服务的连接。
继续执行SQL语句。
mysql> select @@server_uuid,@@server_id;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 3028
Current database: *** NONE ***
+--------------------------------------+-------------+
| @@server_uuid | @@server_id |
+--------------------------------------+-------------+
| c7c6e72e-b9fc-11e8-bf3f-000c29957c4d | 203 |
+--------------------------------------+-------------+
1 row in set (0.02 sec)
这次执行相当于重试功能,执行成功了,但是访问的是203节点上的MySQL服务。就是说haproxy自动检测到了202节点的故障后自动屏蔽了对202节点的访问,同时透明的将mysql客户端的访问转移到了203节点上了,而203节点目前处于在线状态,因此这次执行成功了。
原文地址:https://www.cnblogs.com/coe2coe/p/9751633.html