1、简述keepalived工作原理
Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。
Keepalived采用是模块化设计,不同模块实现不同的功能。
keepalived主要有三个模块,分别是core、check和vrrp。
core:是keepalived的核心,负责主进程的启动和维护,全局配置文件的加载解析等
check: 负责healthchecker(健康检查),包括了各种健康检查方式,以及对应的配置的解析包括LVS的配置解析;可基于脚本检查对IPVS后端服务器健康状况进行检查
vrrp:VRRPD子进程,VRRPD子进程就是来实现VRRP协议的
Keepalived配置文件:keepalived.conf
主要有三个配置区域,分别是:全局配置(Global Configuration)、VRRPD配置、LVS配置
全局配置又包括两个子配置: 全局定义(global definition) 静态IP地址/路由配置(static
ipaddress/routes)
Keepalived服务VRRP的工作原理:
Keepalived高可用对之间是通过 VRRP进行通信的, VRRP是通过竞选机制来确定主备的,主的优先级高于备,因此,工作时主会优先获得所有的资源,备节点处于等待状态,当主宕机的时候,备节点就会接管主节点的资源,然后顶替主节点对外提供服务
在Keepalived服务对之间,只有作为主的服务器会一直发送 VRRP广播包,告诉备它还活着,此时备不会抢占主,当主不可用时,即备监听不到主发送的广播包时,就会启动相关服务接管资源,保证业务的连续性.接管速度最快
出现脑裂的原因:
高可用服务器对之间心跳线链路发生故障,导致无法正常通信。
因心跳线坏了(包括断了,老化)。
因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)
因心跳线间连接的设备故障(网卡及交换机)
因仲裁的机器出问题(采用仲裁的方案)
高可用服务器上开启了 iptables防火墙阻挡了心跳消息传输。
高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败
其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等。
如何解决脑裂:
① 同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个还是好的,依然能传送心跳消息。
② 当检测到裂脑时强行关闭一个心跳节点(这个功能需特殊设备支持,如Stonith、feyce)。相当于备节点接收不到心跳消患,通过单独的线路发送关机命令关闭主节点的电源。
③ 做好对裂脑的监控报警(如邮件及手机短信等或值班).在问题发生时人为第一时间介入仲裁,降低损失。管理员可以通过手机回复对应数字或简单的字符串操作返回给服务器.让服务器根据指令自动处理相应故障这样解决故障的时间更短。
2、编译安装haproxy
编译安装HAProxy 2.0 LTS版本,更多源码包下载地址:http://www.haproxy.org/download/
1 解决 lua 环境
HAProxy 支持基于lua实现功能扩展,lua是一种小巧的脚本语言,于1993年由巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组开发,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。
Lua 官网:www.lua.org
Lua 应用场景
� 游戏开发
� 独立应用脚本
� Web 应用脚本
� 扩展和数据库插件,如MySQL Proxy
� 安全系统,如入侵检测系统
1.1 CentOS 基础环境
由于CentOS7 之前版本自带的lua版本比较低并不符合HAProxy要求的lua最低版本(5.3)的要求,因此需要编译安装较新版本的lua环境,然后才能编译安装HAProxy,过程如下:
#当前系统版本
[root@centos7 ~]#lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
#安装基础命令及编译依赖环境
[root@centos7 ~]# yum install gcc readline-devel
[root@centos7 ~]# curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
[root@centos7 ~]# tar zxf lua-5.3.5.tar.gz
[root@centos7 ~]# cd lua-5.3.5
[root@centos7 lua-5.3.5]# make all test
#查看编译安装的版本
[root@centos7 lua-5.3.5]#mkdir /usr/local/lua
[root@centos7 lua-5.3.5]#mv src/ /usr/local/lua/
[root@centos7 lua-5.3.5]#src/lua -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
1.2 Ubuntu 基础环境
#安装基础命令及编译依赖环境
# apt install gcc iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server
nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev
openssh-server libreadline-dev libsystemd-dev
# cd /usr/local/src
# wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
# tar xvf lua-5.3.5.tar.gz
# cd lua-5.3.5
# make linux test
# pwd
/usr/local/src/lua-5.3.5
# ./src/lua -v
Lua 5.3.3 Copyright (C) 1994-2018 Lua.org, PUC-Rio
#或安装系统自带的lua
# apt install lua5.3=5.3.3-1ubuntu0.18.04.1
# lua5.3 -v
Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio
2 编译安装HAProxy
#HAProxy 1.8及1.9版本编译参数:
make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
#HAProxy 2.0以上版本编译参数:
[root@centos7 ~]#yum -y install gcc openssl-devel pcre-devel systemd-devel
[root@centos7 ~]#tar xvf haproxy-2.4.1.tar.gz -C /usr/local/src
[root@centos7 ~]#cd /usr/local/src/haproxy-2.4.1/
#参考INSTALL文件进行编译安装
[root@centos7 haproxy-2.4.1]#make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/lua/src/ LUA_LIB=/usr/local/lua/src/
[root@centos7 haproxy-2.4.1]# make install PREFIX=/apps/haproxy
[root@centos7 haproxy-2.4.1]# ln -s /apps/haproxy/sbin/haproxy /usr/sbin/
3 验证HAProxy版本
[root@centos7 ~]#haproxy -v
HA-Proxy version 2.4.1 2022/04/17 - https://haproxy.org/
#大写-V选项显示版本和帮助用法
[root@centos7 ~]#haproxy -V
4 准备HAProxy启动文件
#默认缺少配置文件,无法启动
[root@centos7 ~]#systemctl daemon-reload
[root@centos7 ~]#systemctl start haproxy
#创建service文件
[root@centos7 ~]#vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p
/var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
5 配置文件
#创建自定义的配置文件
[root@centos7 ~]# mkdir /etc/haproxy
[root@centos7 ~]# vim /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
#uid 99
#gid 99
user haproxy
group haproxy
daemon
#nbproc 4
#cpu-map 1 0
#cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local2 info
defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 10.0.0.7:80
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
6 启动 haproxy
#准备socket文件目录
[root@centos7 ~]# mkdir /var/lib/haproxy
#设置用户和目录权限
[root@centos7 ~]# useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy
[root@centos7 ~]# systemctl enable --now haproxy
7 验证 haproxy 状态
haproxy.cfg文件中定义了chroot、pidfile、user、group等参数,如果系统没有相应的资源会导致haproxy无法启动,具体参考日志文件 /var/log/messages
[root@centos7 ~]# systemctl status haproxy
8 查看haproxy的状态页面
浏览器访问: http://10.0.0.17:9999/haproxy-status
3、总结haproxy各调度算法的实现方式及其应用场景
HAProxy通过固定参数 balance 指明对后端服务器的调度算法,该参数可以配置在listen或backend选项中 。
HAProxy的调度算法分为静态和动态调度算法,但是有些算法可以根据参数在静态和动态算法中相互转换。
1 静态算法
静态算法:按照事先定义好的规则轮询进行调度,不关心后端服务器的当前负载、连接数和响应速度等,且无法实时动态修改权重(只能为0和1,不支持其它值)或者修改后不生效,如果需要修改只能靠重启HAProxy生效。
1.1 socat 工具
对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版.Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式。如 IP、TCP、 UDP、IPv6、Socket文件等
[root@proxy ~]#yum -y install socat
[root@proxy ~]#vim /etc/haproxy/haproxy.cfg #主配置设置两个进程
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
[root@proxy ~]#echo "get weight m44_webservers1/rs1" | socat stdio /var/lib/haproxy/haproxy.sock1
1 (initial 1)
[root@proxy ~]#echo "get weight m44_webservers1/rs1" | socat stdio /var/lib/haproxy/haproxy.sock2
1 (initial 1)
[root@proxy ~]#echo "set weight m44_webservers1/rs1 0" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "set weight m44_webservers1/rs1 0" | socat stdio /var/lib/haproxy/haproxy.sock2
#测试
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@proxy ~]#echo "disable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "disable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock2
#测试
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@proxy ~]#echo "enable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "enable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock2
#测试
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@proxy ~]#echo "set weight m44_webservers1/rs1 3" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "set weight m44_webservers1/rs1 3" | socat stdio /var/lib/haproxy/haproxy.sock2
#测试
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
1.2 static-rr
static-rr:基于权重的轮询调度,该算法与轮循算法相似,只是它是静态的,这意味着动态更改服务器的权重不会产生任何影响。不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)及后端服务器慢启动,其后端主机数量没有限制,相当于LVS中的 wrr
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance static-rr
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
1.3 first
first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少
不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效
#代码实现
maxconn <maxconn> #当前后端server的最大并发连接数
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance first
server rs1 10.0.0.18:80 maxconn 1 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试,同时运行下面命令,观察结果
[root@client ~]#while true :;do curl http://10.0.0.7/index.html;sleep 0.1;done
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
2 动态算法
动态算法:基于后端服务器状态进行调度适当调整,新请求将优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。
2.1 roundrobin
roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不同于lvs中的rr轮训模式,HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server,支持对real server权重动态调整,roundrobin为默认调度算法,此算法使用广泛
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance roundrobin
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 2 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
2.2 leastconn
leastconn 加权的最少连接的动态,支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接),比较适合长连接的场景使用,比如:MySQL等场景。
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance leastconn
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
2.3 random
在1.9版本开始增加 random的负载平衡算法,其基于随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用,支持weight的动态调整,weight较大的主机有更大概率获取新请求
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance random
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
3 其他算法
其它算法即可作为静态算法,又可以通过选项成为动态算法
3.1 source
源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type选项进行更改
这个算法一般是在不插入Cookie的TCP模式下使用,也可给不支持会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景
源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash
3.1.1 map-base 取模法
map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法
所谓取模运算,就是计算两个数相除之后的余数,10%7=3, 7%4=3
map-based算法:基于权重取模,hash(source_ip)%所有后端服务器相加的总权重
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance source
hash-type map-base
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
3.1.2 一致性 hash
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,
hash(o)mod n ,该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动
算法:
1、key1=hash(source_ip)%(2^32) [0---4294967295]
2、keyA=hash(后端服务器虚拟ip)%(2^32)
3、将key1和keyA都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器
hash环偏斜问题
增加虚拟服务器IP数量,比如:一个后端服务器根据权重为1生成1000个虚拟IP,再hash。而后端服务器权重为2则生成2000的虚拟IP,再进行hash运算,最终在hash环上生成3000个节点,从而解决hash环偏斜问题
3.1.2.1 hash对象
Hash对象到后端服务器的映射关系:
3.1.2.2 一致性hash示意图
后端服务器在线与离线的调度方式
#代码实现
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance source
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
3.2 uri
基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器,适用于后端是缓存服务器场景,默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash。
注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp
#代码实现
[root@rs1 ~]#cd /var/www/html
[root@rs1 html]#for i in {1..10};do echo test$i on 10.0.0.18 > test$i.html;done
[root@rs2 ~]#cd /var/www/html
[root@rs2 html]#for i in {1..10};do echo test$i on 10.0.0.28 > test$i.html;done
#uri一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance uri
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test2.html
test2 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
3.3 url_param
url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server,如果无没key,将按roundrobin算法
#假设
url = http://www.baidu.com/foo/bar/index.php?key=value
#则
host = "www.baidu.com"
url_param = "key=value"
#代码实现
#url_param一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance url_param userid
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html?userid=gu
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7index.html?userid=gu
10.0.0.18
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
3.4 hdr
针对用户每个http头部(header)请求中的指定信息做hash,此处由 name 指定的http首部将会被取出并做hash计算,然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。
#代码实现
#hdr一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance hdr(User-Agent)
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#测试
[root@client ~]#curl 10.0.0.7/index.html
10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test2.html
test2 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.18
[root@client ~]#curl -A "IE"10.0.0.7/test4.html
test4 on 10.0.0.28
[root@client ~]#curl -A "Chrome18"10.0.0.7/test4.html
test4 on 10.0.0.18
[root@client ~]#curl -A "Chrome28"10.0.0.7/test4.html
test4 on 10.0.0.28
[root@client ~]#curl -A "firefox"10.0.0.7/test4.html
test4 on 10.0.0.18
3.5 rdp-cookie
rdp-cookie对windows远程桌面的负载,使用cookie保持会话,默认是静态,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash。
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_rdp_3389
bind 10.0.0.100:3389
mode tcp
balance rdp-cookie
hash-type consistent
server rdp1 10.0.0.200:3389
[root@haproxy ~]#systemctl reload haproxy..service
[root@haproxy ~]#ss -ntl #10.0.0.100:3389端口打开
#测试
windows命令行输入mstsc
4 算法总结
#静态
static-rr--------->tcp/http
first------------->tcp/http
#动态
roundrobin-------->tcp/http
leastconn--------->tcp/http
random------------>tcp/http
#以下静态和动态取决于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http
rdp-cookie-------->tcp
5 各种算法使用场景
first #使用较少
static-rr #做了session共享的 web 集群
roundrobin
random
leastconn #数据库
source #基于客户端公网 IP 的会话保持
Uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿里云、腾讯
url_param--------->http #可以实现session保持
hdr #基于客户端请求报文头部做下一步处理
rdp-cookie #基于Windows主机,很少使用
4、使用haproxy的ACL实现基于文件后缀名的动静分离
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
frontend m44_web_80
bind 10.0.0.100:80
###################### acl setting #########################
acl acl_static path_end -i .jpg .jpeg .png .gif .css .js .html .htm #基于文件后缀名
acl acl_php path_end -i .php
###################### acl hosts ##########################
use_backend static_hosts if acl_static
use_backend app_hosts if acl_php
default_backend app_hosts
#################### backend hosts ########################
backend static_hosts
server rs1 10.0.0.18:80 check
backend app_hosts
server rs2 10.0.0.28 check
[root@haproxy ~]#systemctl restart haproxy.service
#分别在后端两台主机准备相关文件
[root@centos18 ~]#ls /var/www/html
index.html wang.jpg
[root@centos28 ~]#cat /var/www/html/test.php
<?php
echo "<h1>http://10.0.0.28/test.php</h1>\n";
?>
#测试
[root@client ~]#curl 10.0.0.100/wang.jpg
10.0.0.18
[root@client ~]#curl 10.0.0.100/test.php
10.0.0.28