背景描述
目前我们的高可用DB的代理层采用的是360开源的Atlas,从上线以来,已稳定运行2个多月。无论是从性能上,还是稳定性上,
相比其他开源组件(amoeba、cobar、MaxScale、MySQL-Proxy等),还是很出色的。

当初我们之所以选择Atlas,主要看中它有以下优点:
(1)、基于mysql-proxy-0.8.2进行修改,代码完全开源;
(2)、比较轻量级,部署配置也比较简单;
(3)、支持DB读写分离;
(4)、支持从DB读负载均衡,并自动剔除故障从DB;
(5)、支持平滑上下线DB;
(6)、具备较好的安全机制(IP过滤、账号认证);
(7)、版本更新、问题跟进、交流圈子都比较活跃。

在测试期间以及线上问题排查过程中,得到了360 Atlas作者朱超的热心解答,在此表示感谢。有关更多Atlas的介绍,我就不一一例举,
可以参考以下链接:
https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md

2、总体架构图
wKioL1Sw6iagbaHjAAJX6OZk-GM940.jpg

3、系统环境
CentOS 6.3 x86_64

需注意的地方
(1)、本次安装不使用系统默认的glib库,之前的yum安装只是为了先解决依赖库的问题;
(2)、LUA库的版本不能太高,为5.1.x即可;
(3)、glib库的版本也不能太高,为glib-2.32.x即可;
(4)、对于编译不成功的情况,注意查看下面的说明。


yum install glib glib-devel ncurses readline lua  libevent libevent-devel openssl openssl-devel -y

https://github.com/Qihoo360/Atlas/wiki/

从https://github.com/Qihoo360/Atlas/releases 页面下载最新版RPM包,然后执行:
sudo rpm –i Atlas-XX.el6.x86_64.rpm安装。 

Atlas运行需要依赖一个配置文件(test.cnf)。在运行Atlas之前,需要对该文件进行配置。Atlas的安装目录是/usr/local/mysql-proxy,
进入安装目录下的conf目录,可以看到已经有一个名为test.cnf的默认配置文件,我们只需要修改里面的某些配置项,不需要从头写一个配置文件。

1.配置范例及说明如下:
[mysql-proxy]

(必备,默认值即可)管理接口的用户名
admin-username = user
(必备,默认值即可)管理接口的密码
admin-password = pwd
(必备,根据实际情况配置)主库的IP和端口
proxy-backend-addresses = 192.168.0.12:3306
(非必备,根据实际情况配置)从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔。
如果想让主库也能分担读请求的话,只需要将主库信息加入到下面的配置项中。
proxy-read-only-backend-addresses = 192.168.0.13:3306,192.168.0.14:3306
(必备,根据实际情况配置)用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,用户名与密码
之间用冒号分隔。主从数据库上需要先创建该用户并设置密码(用户名和密码在主从数据库上要一致)。比如用户名为myuser,密码为mypwd,
执行./encrypt mypwd结果为HJBoxfRsjeI=。如果有多个用户用逗号分隔即可。则设置如下行所示:
pwds = myuser: HJBoxfRsjeI=,myuser2:HJBoxfRsjeI=
(必备,默认值即可)Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时
设为true
daemon = true
(必备,默认值即可)设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退
出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true
keepalive = true
(必备,根据实际情况配置)工作线程数,推荐设置成系统的CPU核数的2至4倍
event-threads = 4
(必备,默认值即可)日志级别,分为message、warning、critical、error、debug五个级别
log-level = message
(必备,默认值即可)日志存放的路径
log-path = /usr/local/mysql-proxy/log
(必备,根据实际情况配置)SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,该模式下日志
刷新是基于缓冲区的,当日志填满缓冲区后,才将日志信息刷到磁盘。REALTIME用于调试,代表记录SQL日志且实时写入磁盘,默认为OFF
sql-log = OFF
(可选项,可不设置)慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该
参数则输出全部日志。
sql-log-slow = 10
(可选项,可不设置)关闭不活跃的客户端连接设置。当设置了该参数时,Atlas会主动关闭经过'wait-timeout'时间后一直未活跃的连接。单位:秒
wait-timeout = 10
(必备,默认值即可)Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234
(必备,默认值即可)Atlas监听的管理接口IP和端口 admin-address = 0.0.0.0:2345
(可选项,可不设置)分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不
需要设置该项,子表需要事先建好,子表名称为表名_数字,数字范围为[0,子表数-1],如本例里,子表名称为mt_0、mt_1、mt_2
tables = person.mt.id.3
(可选项,可不设置)默认字符集,若不设置该项,则默认字符集为latin1
charset = utf8
(可选项,可不设置)允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则
只允许列表中的IP连接
client-ips = 127.0.0.1, 192.168.1
(可选项,极少需要)Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
lvs-ips = 192.168.1.1

2. 重要配置说明
以下几项配置参数对性能和正常运行起到重要作用,需要正确设置。
(1)线程数
event-threads项设置,过小无法充分发挥多核CPU的性能,过大造成不必要的线程切换开销,推荐设置为CPU的核数。
(2)最小空闲连接数(2.x以上版本不需要该项,1.x版本需要)
min-idle-connections项设置,过小则在高并发下会有报错,过大虽然不报错但在测试时不容易看出读写分离效果,推荐设置为比客户端
的并发峰值稍大,详见《配置参数详解》。上面的配置范例是针对Atlas 2.X版本,没有该选项。对于Atlas 1.X版本的配置文件,需要加入
该配置选项。
3. 可选配置说明
以下几项可以设置,也可以使用默认值,区别不大。
(1)Atlas的工作端口
proxy-address项配置,例如proxy-address = 0.0.0.0:1234代表客户端应该使用1234这个端口连接Atlas来发送SQL请求。
(2)Atlas的管理端口
admin-address项配置,例如admin-address = 0.0.0.0:2345代表DBA应该使用2345这个端口连接Atlas来执行运维管理操作。
(3)管理接口的用户名和密码
admin-username项和admin-password项设置,这两项是用来进入Atlas的管理界面的,与后端连接的MySQL没有关系,所以可以任意设
置,不需要MySQL在配置上做任何改动。
(4)日志级别
以log-level项配置,分为message、warning、critical、error、debug五个级别
(5)日志路径
以log-path项配置,如log-path = /usr/local/mysql-proxy/log。

进入/usr/local/mysql-proxy/bin目录,执行下面的命令启动、重启或停止Atlas。
(1). sudo ./mysql-proxyd test start,启动Atlas。
(2). sudo ./mysql-proxyd test restart,重启Atlas。
(3). sudo ./mysql-proxyd test stop,停止Atlas。
注意:
(1). 运行文件是:mysql-proxyd(不是mysql-proxy)。
(2). test是conf目录下配置文件的名字,也是配置文件里instance项的名字,三者需要统一。
(3). 可以使用ps -ef | grep mysql-proxy查看Atlas是否已经启动或停止。
执行命令:mysql -h127.0.0.1 -P1234 -u用户名 -p密码,如果能连上则证明Atlas初步测试正常,可以再尝试发几条SQL语句看看执行
结果是否正确。
进入Atlas的管理界面的命令:mysql -h127.0.0.1 -P2345 -uuser -ppwd,进入后执行:select * from help;查看管理DB的各类命令。

Atlas高可用【Keepalived】
(1)、主节点配置
# vim /etc/keepalived/keepalived.conf

global_defs {
    notification_email {
        [email protected]
    }

    notification_email_from [email protected]
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id dbproxy1
}

vrrp_script chk_mysql_proxy_health {
    script "/data/scripts/keepalived_check_mysql_proxy.sh"
    interval 1
    weight -2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth1
    virtual_router_id 51
    priority 100
    advert_int 1
    smtp_alert

    authentication {
        auth_type PASS
        auth_pass 123456
    }

    virtual_ipaddress {
        10.209.6.115
    }

    track_script {
        chk_mysql_proxy_health
    }

    notify_master "/data/scripts/notify.sh master"
    notify_bakcup "/data/scripts/notify.sh backup"
    notify_fault "/data/scripts/notify.sh fault"
}
(2)、备用节点配置
# vim /etc/keepalived/keepalived.conf

global_defs {
    notification_email {
        [email protected]
    }

    notification_email_from [email protected]
    smtp_server 127.0.0.1
    smtp_connect_timeout 30
    router_id dbproxy2
}

vrrp_script chk_mysql_proxy_health {
    script "/data/scripts/keepalived_check_mysql_proxy.sh"
    interval 1
    weight -2
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth1
    virtual_router_id 51
    priority 90
    advert_int 1
    smtp_alert

    authentication {
        auth_type PASS
        auth_pass 123456
    }

    virtual_ipaddress {
        10.209.6.115
    }

    track_script {
        chk_mysql_proxy_health
    }

    notify_master "/data/scripts/notify.sh master"
    notify_bakcup "/data/scripts/notify.sh backup"
    notify_fault "/data/scripts/notify.sh fault"
}
(3)、VIP切换通知脚本
# vim /data/scripts/notify.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

KEEPALIVE_CONF="/etc/keepalived/keepalived.conf"

VIP=`grep -A 1 virtual_ipaddress ${KEEPALIVE_CONF} | tail -1 | sed 's/\t//g; s/ //g'`
ETH1_ADDR=`/sbin/ifconfig eth1 | awk '/inet addr:/{print $2}' | awk -F: '{print $2}'`

MONITOR="/usr/local/oms/agent/alarm/BusMonitorAgent"
TOKEN="ha_monitor"

function notify() {
    TITLE="$ETH1_ADDR to be $1: $VIP floating"
    CONTENT="vrrp transition, $ETH1_ADDR changed to be $1"
    ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}"
}

case "$1" in
master)
    notify master
    exit 0
    ;;

backup)
    notify backup
    exit 0
    ;;

fault)
    notify fault
    exit 0
    ;;

*)
    echo 'Usage: `basename $0` {master|backup|fault}'
    exit 1
    ;;
esac
(4)、DB中间层进程检查脚本
# vim /data/scripts/keepalived_check_mysql_proxy.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

if [[ `pgrep mysql-proxy | wc -l` -eq 0 ]]; then
    /sbin/service mysql-proxy start && sleep 5
    [[ -z `pgrep mysql-proxy` ]] && /sbin/service keepalived stop
fi
# chmod +x /data/scripts/*.sh
# service keepalived start
wKioL1Sw72OBWcdcAABQovflyow736.jpg
# ip addr show eth1
wKiom1Sw7r3S6v6_AACfXZvxonQ064.jpg
# ps aux | grep keepalive[d]
wKiom1Sw7tnzsSOAAABqz91YIVo562.jpg

==========================================================================================
三、其他设置
==========================================================================================
1、Atlas服务监控
# vim /usr/local/mysql-proxy/bin/check_service.sh

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

[[ $# -ne 3 ]] && echo "$0 端口号 协议类型 服务名" && exit 1

SRV_PORT=$1  ## 端口号
SRV_PROT=$2  ## 协议类型
SRV_NAME=$3  ## 服务名

MONITOR="/usr/local/oms/agent/alarm/BusMonitorAgent"
TOKEN="ha_monitor"

TITLE="${SRV_NAME}服务异常监控"
CONTENT="${SRV_NAME}服务发生异常,已自动拉起!"

## 是否已正确扫描
SCAN_FLAG=0

function RESTART_SRV_AND_ALERT() 
{
    local CUR_SRV_NAME

    [[ $# -ne 1 ]] && exit 1
    CUR_SRV_NAME=$1

    TMP_SRV_NAME=`echo ${CUR_SRV_NAME} | tr '[A-Z]' '[a-z]'`
    [[ ! -f /etc/init.d/${TMP_SRV_NAME} ]] && TMP_SRV_NAME="${TMP_SRV_NAME}d"

    killall -9 ${TMP_SRV_NAME}

    if [[ -z `ps aux | grep ${TMP_SRV_NAME} | grep -v grep` ]]; then
        /sbin/service ${TMP_SRV_NAME} start >/dev/null 2>&1
    fi

    ${MONITOR} -c 2 -f ${TOKEN} -t "${TITLE}" -i "${CONTENT}"
    rm -f `pwd`/connect_error.log
}

ETH1_ADDR=`/sbin/ifconfig eth1 | awk -F ':' '/inet addr/{print $2}' | sed 's/[a-zA-Z ]//g'`
TMP_SRV_PROT=`echo ${SRV_PROT} | tr '[A-Z]' '[a-z]'`

if [[ "${TMP_SRV_PROT}" == "tcp" ]]; then
    PROT_OPT="S"
elif [[ "${TMP_SRV_PROT}" == "udp" ]]; then
    PROT_OPT="U"
else
    echo "未知的协议类型!" && exit 1
fi

## 最多扫描3次,成功一次即可,以避免网络抖动而导致误判
for ((i=0; i<3; i++)); do
    RETVAL=`/usr/bin/nmap -n -s${PROT_OPT} -p ${SRV_PORT} ${ETH1_ADDR} | grep open`
    [[ -n "${RETVAL}" ]] && SCAN_FLAG=1;break || sleep 10
done

## 1、针对Atlas服务端口不通的情况,也就是服务彻底挂掉
[[ ${SCAN_FLAG} -ne 1 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}

## 2、检查Atlas服务是否正常工作,也就是服务端口正常,但访问异常的情况【高权限DB用户】
mysqladmin -h${ETH1_ADDR} -uhealth_check1 -p123456 --connect-timeout=15 --shutdown-timeout=15 ping
[[ $? -ne 0 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}

## 3、检查Atlas服务是否正常工作,也就是服务端口正常,高权限DB用户访问也正常,但低权限
##    DB用户访问异常的情况【低权限DB用户】
mysqladmin -h${ETH1_ADDR} -uhealth_check2 -p123456 --connect-timeout=15 --shutdown-timeout=15 ping
[[ $? -ne 0 ]] && RESTART_SRV_AND_ALERT ${SRV_NAME}
2、Atlas访问日志切割
# vim /data/scripts/cut_and_clear_access_log.sh

#!/bin/sh
# 切割Atlas的访问日志,同时清理15天之前的日志
#
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

## mysql-proxy日志路径
LOGPATH="/usr/local/mysql-proxy/log"

[[ `/sbin/ip addr show eth1 | grep inet | wc -l` -eq 2 ]] || exit 1 
cd ${LOGPATH}

## 日志切割
HISTORY_LOG_PATH=`date -d '-1 hour' +"%Y-%m-%d/sql_mysql-proxy_%H.log"`
[[ -d `dirname ${HISTORY_LOG_PATH}` ]] || mkdir -p `dirname ${HISTORY_LOG_PATH}`
cp -a sql_mysql-proxy.log ${HISTORY_LOG_PATH}

echo > sql_mysql-proxy.log

## 日志清理
HISTORY_LOG_PATH=`date -d '15 days ago' +'%Y-%m-%d'`
[[ -d ${HISTORY_LOG_PATH} ]] && rm -rf ${HISTORY_LOG_PATH}
3、crontab内容添加
# touch /var/lock/check_service.lock
# echo 'touch /var/lock/check_service.lock' >> /etc/rc.d/rc.local
# crontab -uroot -e
1
2
* * * * * (flock --timeout=0 /var/lock/check_service.lock /usr/local/mysql-proxy/bin/check_service.sh 
3306 tcp mysql-proxy >/dev/null 2>&1)
00 * * * * /data/scripts/cut_and_clear_access_log.sh >/dev/null 2>&1
4、平滑设置功能
# mysql -h10.209.6.101 -P3307 -usysadmin -p'admin2356!@()'
wKioL1Sw8S_gXZOuAALgQK7R39c195.jpg

results matching ""

    No results matching ""