- HAProxy的调度算法分为静态调度算法、动态调度算法和其他调度算法
- 静态算法:按照事先定义好的规则轮询公平调度,不关⼼后端服务器的当前负载、链接数和响应速度等,且⽆法实时修改权重,只能靠重启HAProxy⽣效。
- 动态算法:基于后端服务器 状态进⾏调度适当调整,⽐如优先调度⾄当前负载较低的服务器,且权重可以在haproxy运⾏时动态调整⽆需重启。
- 其他算法:即可作为静态算法,⼜可以通过选项成为动态算法
一.静态调度算法
1.1 static-rr:基于权重的轮询调度
- 不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)
- 不支持端服务器慢启动
- 其后端主机数量没有限制,相当于LVS中的 wrr
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
# balance roundrobin
balance static-rr
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
1.2first
- 根据服务器在列表中的位置,自上而下进行调度
- 其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务
- 其会忽略服务器的权重设置
- 不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
balance first # maxconn 1 不合理,为了明显查看实验结果
server web1 172.25.254.10:80 maxconn 1 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
### 测试
[root@webserver1 ~]# while true ; do curl 172.25.254.100;sleep 0.1;done
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
[root@webserver2 ~]# while true; do curl 172.25.254.100;sleep 0.1;done
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
二.动态调度算法
- 基于后端服务器状态进行调度适当调整
- 新请求将优先调度至当前负载较低的服务器
- 权重可以在haproxy运行时动态调整无需重启
2.1roundrobin
- 基于权重的轮询动态调度算法
- 支持权重的运行时调整,不同于Is中的rr轮训模式
- HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数)
- 其每个后端backend中最多支持4095个realserver
- 持对real server权重动态调整
- roundrobin为默认调度算法,此算法使用广泛
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
balance roundrobin
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
# 测试
web1死循环
[root@webserver2 ~]# while true; do curl 172.25.254.100;sleep 0.1;done
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
web2
[root@webserver2 ~]# while true; do curl 172.25.254.100;sleep 0.1;done
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
###测试
负载小的访问多
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
支持动态调整权重
[root@haproxy ~]# echo "set weight webcluster/web1 1 " | socat stdio /var/lib/haproxy/stats
[root@haproxy ~]# echo "get weight webcluster/web1 " | socat stdio /var/lib/haproxy/stats
1 (initial 2)
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# echo "get weight webcluster/web1 " | socat stdio /var/lib/haproxy/stats
2 (initial 2)
[root@haproxy ~]# echo "set weight webcluster/web1 1 " | socat stdio /var/lib/haproxy/stats
2.2leastconn
- leastconn加权的最少连接的动态
- 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
- 比较适合长连接的场景使用,比如:MySQL等场景
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
balance leastconn
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
webserver1 - 172.25.254.10
webserver2 - 172.25.254.20
2.3其他算法
其它算法即可作为静态算法,又可以通过选项成为动态算法
2.3.1source
- 源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项更改这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
#balance leastconn
balance source
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
# 测试
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
webserver2 - 172.25.254.20
[root@haproxy ~]#
2.3.1.1map-bash取模法
此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度
缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法
比如当源hash值时1111,1112,1113,三台服务器abc的权重均为1,即abc的调度标签分别会被设定为012(1111%3=1,1112%3=2,1113%3=0)假设a为 0,1113主机会被调度到a上如果a下线后,权重数量发生变化1111%2=1,1112%2=0,1113%2=11112和1113被调度到的主机都发生变化,这样会导致会话丢失
2.3.1.2一致性hash
算法
1、后端服务器哈希环点keyA=hash(后端服务器虚拟ip)%(2^32)
2、客户机哈希环点key1=hash(client_ip)%(2^32) 得到的值在[0---4294967295]之间,
3、将keyA和key1都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器
该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持启动
【哈希环时一个0-2^32-1的数字被落到了一个圆上】
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
#balance leastconn
balance source
hash-type consistent
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
#server web_s 172.25.254.100:8080 backup
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# echo "set weight webcluster/web1 1 " | socat stdio /var/lib/haproxy/stats
2.3.2uri
基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后
根据最终结果将请求转发到后端指定服务器
适用于后端是缓存服务器场景
默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash
注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp
<scheme>://<user>:<password>@<host>:<port>/<path>【路径】;<params>【传递的命令】?<query>【搜索的字段】#<frag>
左半部分:/<path>;<params>
整个uri:/<path>;<params>?<query>#<frag>
url:整个服务器的真实位置
2.3.2.1uri一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
#balance leastconn
#balance source
balance uri
hash-type consistent
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
[root@haproxy ~]# systemctl restart haproxy.service
[root@webserver1 ~]# echo 172.25.254.10 - index.html > /usr/share/nginx/html/index.html
[root@webserver1 ~]# echo 172.25.254.10 - index2.html > /usr/share/nginx/html/index2.html
[root@webserver1 ~]# echo 172.25.254.10 - index3.html > /usr/share/nginx/html/index3.html
[root@webserver2 ~]# echo 172.25.254.20 - index.html > /usr/share/nginx/html/index.html
[root@webserver2 ~]# echo 172.25.254.20 - index2.html > /usr/share/nginx/html/index2.html
[root@webserver2 ~]# echo 172.25.254.20 - index3.html > /usr/share/nginx/html/index3.html
测试
[root@haproxy ~]# curl 172.25.254.100/index.html
172.25.254.10 - index.html
[root@haproxy ~]# curl 172.25.254.100/index2.html
172.25.254.20 - index2.html
[root@haproxy ~]# curl 172.25.254.100/index3.html
172.25.254.10 - index3.html
2.3.2.2 url_param
url param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器,后端搜索同一个数据会被调度到同一个服务器,多用与电商
通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个realserver
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
#balance leastconn
#balance source
#balance uri
balance url_param name,userid
hash-type consistent
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 1
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
测试
[root@haproxy ~]# curl 172.25.254.100/index.html?name=gg
172.25.254.10 - index.html
[root@haproxy ~]# curl 172.25.254.100/index.html?name=gg
172.25.254.10 - index.html
[root@haproxy ~]# curl 172.25.254.100/index.html?name=test
172.25.254.20 - index.html
[root@haproxy ~]# curl 172.25.254.100/index.html?name=test
172.25.254.20 - index.html
2.3.3hdr
针对用户每个http头部(header)请求中的指定信息做hash,
此处由 name 指定的http首部将会被取出并做hash计算
然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。
listen webcluster
bind *:80
mode http
#balance roundrobin
#balance static-rr
#balance first
#balance leastconn
#balance source
#balance uri
#balance url_param name,userid
balance hdr(User-Agent)
hash-type consistent
server web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2
server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
测试
[root@haproxy ~]# curl 172.25.254.100/index.html
172.25.254.10 - index.html
[root@haproxy ~]# curl 172.25.254.100/index.html
172.25.254.10 - index.html
[root@haproxy ~]# curl 172.25.254.100/index.html
172.25.254.10 - index.html
三. 算法总结
静态:
static-rr--------->tcp/http #做session共享的web集群
first------------->tcp/http #使⽤较少
动态:
roundrobin-------->tcp/http
leastconn--------->tcp/http #数据库
random------------>tcp/http
取决于是否有hash_type consistent,有为动态,默认静态:
source------------>tcp/http #基于客户端公⽹IP的会话保持
uri--------------->http #缓存服务器,CDN服务商,蓝汛、百度、阿⾥云、腾讯
url_param--------->http
hdr--------------->http #基于客户端请求报⽂头部做下⼀步处理
rdp-cookie-------->tcp #很少使⽤
uri、url_param、hdr只有在mode为http的情况下才能取到值,如果mode为tcp,balance自动更改为roundrobin。
动态与静态最主要区别:可以用socat动态调整权重、支持慢启动功能。