MySQL集群架构06HAProxy+PXC集群架构

本博客讨论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文件内容如下:

[root@201 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服务控制脚本。

[root@201 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。

[root@201 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脚本:

[root@201 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端口的服务是否正常工作。

[root@201 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

[root@201 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端口来测试负载均衡的节点分配情况。

[root@203 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端口。

[root@203 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节点目前处于在线状态,因此这次执行成功了。

猜你喜欢

转载自www.cnblogs.com/coe2coe/p/9751633.html