Linux云计算架构-使用HAProxy实现负载均衡集群
1. HAProxy介绍
从HAProxy的字面意思可以看到,是由HA+Proxy
,即可以实现高可用和代理。HAProxy是一种提供高可用、负载均衡以及基于TCP和HTTP应用的代理的,支持虚拟主机的,免费、快速、可靠的解决方案。官方数据表明最高极限支持10G的并发访问。
HAproxy也是通过反向代理的方式实现web的负载均衡,但是与nginx实现负载均衡不同的是,nginx本身是属于web服务器的,而HAproxy只是一款用于负载均衡的软件,本身并不提供web服务。
HAproxy配置简单,并且拥有服务器健康检查功能和专门的系统状态监控页面,当代理的后端服务器出现故障,HAproxy会将其从负载均衡集群中剔除,恢复后会将服务器自动加入负载均衡集群。
2. HAProxy部署
环境介绍:
主机名 | IP地址 | 作用 |
---|---|---|
server | 192.168.8.128 | haproxy代理服务器,负责负载均衡调度 |
rs1 | 192.168.8.129 | 后端服务器 |
rs2 | 192.168.8.130 | 后端服务器 |
拓扑图:
下载haproxy软件包: https://github.com/haproxy/haproxy/releases/
[root@server ~]# ll haproxy-2.3-dev8.tar.gz
-rw-r--r--. 1 root root 2905297 10月 29 20:35 haproxy-2.3-dev8.tar.gz
[root@server ~]# tar xzf haproxy-2.3-dev8.tar.gz
[root@server ~]# cd haproxy-2.3-dev8/
[root@server haproxy-2.3-dev8]# cat INSTALL
[root@server ~]# uname -r
3.10.0-957.el7.x86_64
# 通过查看INSTALL文件,可以看到要安装haproxy软件包,需要内核在linux2.6.28以上版本,我这里的是3.10.0
# 安装依赖
[root@server haproxy-2.3-dev8]# yum -y install make gcc gcc-c++ openssl-devel
# 编译安装
# 可以提前在Makefile文件中修改TARGET和PREFIX参数值,然后直接make && make install
# 否则只能make和make install都指定PREFIX参数
[root@server haproxy-2.3-dev8]# make TARGET=linux3100 PREFIX=/usr/local/haproxy
[root@server haproxy-2.3-dev8]# make install PREFIX=/usr/local/haproxy
[root@server haproxy]# pwd
/usr/local/haproxy
[root@server haproxy]# ll
总用量 0
drwxr-xr-x. 3 root root 21 10月 29 23:12 doc
drwxr-xr-x. 2 root root 21 10月 29 23:12 sbin
drwxr-xr-x. 3 root root 17 10月 29 23:12 share
创建haproxy的配置文件: /usr/local/haproxy/etc/haproxy.cfg
[root@server ~]# mkdir /usr/local/haproxy/etc
[root@server ~]# cd /usr/local/haproxy/etc
[root@server etc]# vim haproxy.cfg
global # 全局配置
log 127.0.0.1 local0
maxconn 4096
chroot /usr/local/haproxy # haproxy安装目录
uid 99 # 运行用户,默认存在的,用户名为nobody,可用id 99查看
gid 99 # 运行用户组
daemon # 后台运行haproxy
nbproc 1 # 启动的进程数,计划在2.5中删除该参数,改用多线程代替多线程。可以注释掉或者改为1个进程
pidfile /usr/local/haproxy/run/haproxy.pid # 进程PID文件,记录所有的进程
defaults # 默认配置
log global
log 127.0.0.1 local3 # 日志文件的输入定向,日志级别为local3
mode http # 工作模式,默认为http模式,也可以是tcp模式。
option httplog # 日志类别,记录http日志
option httpclose # 每次请求完毕后主动关闭http连接通道,haproxy不支持长连接。
option dontlognull # 不记录空连接产生的日志
option forwardfor # 若后端真实服务器需要获取客户端的IP,则需要配置该参数,可用http header 中获取客户端的IP地址。
option redispatch # 当serverid对应的服务器挂了,强制定向到其他健康的服务器。
retries 2 # 检查服务器是否可用的尝试次数
maxconn 2000 # 最大连接数
balance roundrobin # 负载均衡算法,这里是rr轮询
stats uri /haproxy-stats # haproxy监控页面的访问地址
timeout connect 5000 # 连接超时时间,单位ms,即5s
timeout client 50000 # 客户端连接超时时间
timeout server 50000 # 服务端连接超时时间
mode http
option httpchk GET /index.html # 健康检测页面,应该是一个小页面,每个1s进行检测该页面
frontend http # 前端配置,http名称可自定义
bind 0.0.0.0:80 # 发起http请求80端口,会被转发到该IP地址和端口
default_backend http_back # 后端服务器集群名称
backend http_back # 后端服务器配置
server s1 192.168.8.129:80 weight 3 check # 后端节点配置
server s2 192.168.8.130:80 weight 3 check
#####################################################################
# server node1 后端IP地址 inter 2000 rise 3 fall 3 weight 30
# inner 2000 健康检查时间间隔为2s
# rise 3 健康检查次数,检查3次健康才算健康
# fall 3 失败检查次数,检查3次失败才算失败
# weight 30 权重
#####################################################################
# balance 负载均衡算法
source 根据请求源IP地址分发
static-rr 根据权重分发
leastconn 最少连接者先处理
uri 根据uri分发
uri_param 根据请求的uri参数分发
rdp_cookie 根据cookie来分发,并hash每一次请求
hdr 根据http的请求头分发每一次http请求
roundrobin 轮询
配置haproxy启动脚本:
[root@server ~]# cp ./haproxy-2.3-dev8/examples/haproxy.init /etc/init.d/haproxy
[root@server ~]# ll /etc/init.d/haproxy
-rw-r--r--. 1 root root 2381 10月 30 22:06 /etc/init.d/haproxy
[root@server ~]# chmod 755 /etc/init.d/haproxy
[root@server ~]# vim /etc/init.d/haproxy # 修改5个位置
#!/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=haproxy # 定义变量
BIN=/usr/sbin/haproxy # 定义haproxy二进制命令的位置
CFG=/usr/local/haproxy/etc/haproxy.cfg # 定义haproxy的配置文件位置
[ -f $CFG ] || exit 1
PIDFILE=/usr/local/haproxy/run/haproxy.pid # PID进程文件
LOCKFILE=/usr/local/haproxy/run/haproxy # 文件存在,就说明haproxy在运行
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 $?
# 配置二进制文件BIN
[root@server ~]# cp /usr/local/haproxy/sbin/haproxy /usr/sbin/
# 配置PIDFILE和LOCKFILE文件的存放目录
[root@server ~]# mkdir -p /usr/local/haproxy/run
[root@server ~]# chown -R nobody /usr/local/haproxy/
# 配置日志收集,否则无法收集日志。
[root@server ~]# vim /etc/rsyslog.conf
15 $ModLoad imudp
16 $UDPServerRun 514
74 local3.* /var/log/haproxy.log
75 local0.* /var/log/haproxy.log
启动和停止haproxy:
# 启动haproxy
[root@server ~]# /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/etc/haproxy.cfg
# 查看haproxy的状态
[root@server ~]# ps aux | grep haproxy
nobody 8725 0.0 0.0 8480 1496 ? Ss 22:33 0:00 /usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/etc/haproxy.cfg
root 8731 0.0 0.0 112724 988 pts/0 S+ 22:33 0:00 grep --color=auto haproxy
[root@server ~]# netstat -antup |grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 8725/haproxy
# 关闭haproxy
# 若无killall命令,可使用yum install psmisc -y 安装
[root@server ~]# killall haproxy
# 配置开机自启
[root@server ~]# chkconfig --add haproxy
[root@server ~]# chkconfig haproxy on
#################################################################
# 也可以用脚本启动,但看起来像是前台启动,会卡住。故建议用以上方法进行启动和关闭haproxy
[root@server ~]# /etc/init.d/haproxy start
[root@server ~]# systemctl restart haproxy.service
3. 配置后端服务器
[root@rs1 ~]# yum install -y httpd
[root@rs1 ~]# echo "rs1" > /var/www/html/index.html
[root@rs1 ~]# systemctl start httpd
[root@rs1 ~]# systemctl enable httpd
[root@rs1 ~]# netstat -antup | grep httpd
tcp6 0 0 :::80 :::* LISTEN 6870/httpd
[root@rs2 ~]# yum install -y httpd
[root@rs2 ~]# echo "rs2" > /var/www/html/index.html
[root@rs2 ~]# systemctl start httpd
[root@rs2 ~]# systemctl enable httpd
[root@rs2 ~]# netstat -antup | grep httpd
tcp6 0 0 :::80 :::* LISTEN 6853/httpd
# 防火墙开放80端口号,三台主机都要开。
[root@server ~]# firewall-cmd --list-port
80/tcp
4. 测试haproxy负载均衡
输出网址:http://192.168.8.128/haproxy-stats
查看负载均衡统计页面
输入网址:http://192.168.8.128/
随着刷新,每次看到的页面都不一样,说明haproxy
确实有在做负载均衡。
停止rs1的httpd服务,可以看到统计页面上也会显示rs1已经DOWN了,自动将rs1从集群中剔除:
重启rs1上的httpd服务,可以看到rs1又自动加入集群中:
5. 注意点
①haproxy通过检查后端服务器的一个小页面去判断后端服务器是否存活,这个小页面最后是静态小页面。
②由于使用源码包安装,haproxy不存在配置文件,故需要自行创建配置文件,这个估计得自行思考如何配置。
③haproxy的启动脚本,需要掌握shell脚本编程才好理解,但幸好改动的地方不是太多。
④haproxy的统计界面,主要作用是监控后端服务器是否故障,当发现后端服务器故障时,及时修复后端服务器。