haproxy调度算法
调度算法
通过固定参数balance指明对后端服务器的调度算法,该参数可以配置在listen或backend选项中
官方文档:http://cbonte.github.io/haproxy-dconv/2.1/configuration.html#4-balance
socat工具:
为了验证haproxy调度算法的功能,使用使用额外的工具更方便
linux下的多功能的网络工具,全名是socket cat。相当于netcat的增强版
主要用户两个数据流之间建立双向通道,且支持众多协议和连接方式,如:ip、tcp、udp、ipv6、socket文件等
本次使用socat工具对服务器进行动态权重和状态修改
安装:
- yum install -yu socat
使用:
注意:
- 使用前必须在haproxy配置文件中,开启套接字文件的管理员权限:
stats socket /var/lib/haproxy.sock mode 600 level admin process 1
#建议设置一个别名,命令太长,每次都要敲太麻烦
alias sc="socat stdio /var/lib/haproxy/haproxy.sock"
#查看haproxy套接字的帮助命令
echo help |sc
echo help |socat stdio ./haproxy.sock 查看haproxy的套接字支持哪些操作
show info
show sess 当先session信息
show stat 当前haproxy的状态
show servers state 显示当前代理的主机状态信息
disable agent
disable health
disable server 禁用服务器
enable agent
enable health
enable server 启用server
set maxconn server 修改server的最大连接数
set server 后端名/server名 设置server
get weight 后端名/server名 显示当前server的权重
set weight 后端名/server名 设置server的权重
set maxconn global 设置全局额最大连接数
set timeout 修改超时时间
show env 显示环境变量
show cli socket 显示与客户端正在连接的socket
show cli level 显示当前客户端的session会话用户
show activity 显示当前活动状态的线程信息
show cache 缓存相关
show errors 显示代理主机中请求、响应错误的信息
show backend 显示当前的backend主机

例: socat动态修改权重
echo set weight web/web1 5|sc #修改web1的权重为5,如果为每个进程对应了一个socket,那么都要设置,而只有一个socket文件则不需要
echo set weight web/web1 5|socat stdio ./haproxy1.sock
echo set weight web/web1 5|socat stdio ./haproxy2.sock

例: server下线,代码灰度发布
echo set weight b-web/web1 0|sc
echo v2 >> /opt/web/index.html
echo set weight b-web/web1 5|sc
echo set weight b-web/web2 0|sc
echo v2 >> /opt/web/index.html
echo set weight b-web/web2 5|sc
例: 上线下线脚本
#!/bin/bash
. /etc/init.d/functions
case $1 in
up)
echo "set weight prx-web/$2 1" | socat stdio /var/lib/haproxy/haproxy.sock
[ $? -eq 0 ] && action "$2 is up" /bin/true
;;
down)
echo "set weight prx-web/$2 0" | socat stdio /var/lib/haproxy/haproxy.sock
[ $? -eq 0 ] && action "$2 is down" /bin/false
;;
*)
echo "Usage: `basename $0` up|down IP"
;;
esac
算法分类:
静态
- static-rr tcp/http 一般用于做session共享的web集群
- first tcp/http 较少使用
动态
- roundrobin tcp/http 一般用于做session共享的web集群
- leastconn tcp/http 一般用于数据库
- random tcp/http
其他算法 可以根据参数配置实现动态<-->静态相互转换
- source tcp/http 一般用于做客户端公网ip做会话保持
- uri http 用于缓存服务器,如CDN厂商:蓝汛、百度、腾讯、阿里云
- url_param http 一般用于客户端请求参数分类调度
- hdr http 一般用于客户端请求报文分类调度
- rdp-cookie tcp 代理windos主机,较少使用
静态算法:
只能按事先定义好的规则进行公平调度,不关心后端服务器的当前负载、连接数、响应速度等,
无法实时修改权重(是能实时修改位0和1)
只能靠重启haproxy生效
static-rr算法:
- 权重的轮询调度,不支持运行时利用socat进行权重的动态调整(仅支持0和1)
- 不支持后端服务器慢启动,其后端主机数量没有限制,等于lvs的wrr
例:
listen web
bind :80
balance static-rr
server web1 1.1.10:80 weight 1
server web1 1.1.20:80 weight 3
first算法:
- 根据服务器在列表中的位置,自上而下调度,但只会当第一台主机的连接数达到上限,新请求才会分配给下一台主机,因此会忽略权重设置。较少使用
- 不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效
例:
linsten web
bind :80
balance first
server web1 1.1.10:80 weight 1 maxconn 2
server web2 1.1.20:80 weight 3
动态算法:
根据后端服务状态进行适当调整,优先调度至当前负载较低的后端服务器,且支持运行时动态修改权重(不用重启haproxy服务)
roundrobin算法:
- 权重的动态轮询调度算法(默认使用算法,使用最多),可以在运行时调整权重。不同于lvs的rr轮询模式,haproxy的支持慢启动
- 每个后端backend中最多支持4065个real server
- 支持对real server动态调整权重
例:
listen web
balance roundrobin
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 2 check inter 3000 fall 2 rise 5
例2: 动态调整权重
echo set weight 3 web/web1 |sc
echo get weight web/web1 |sc
while true;do curl 127.0.0.1;sleep 0.5;done
leastconn算法:
- 加权的最少连接的状态,根据后端的当前最少连接数进行优先调度,比较适合长链接的场景,如:mysql
- 支持权重动态调整和慢启动
例:
listen web
balance leastconn
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 3 check inter 3000 fall 2 rise 5
random算法:
- 1.9版本增加。随机数作为一致性hash的key,随机调度后端
- 随机负载均衡对于大型服务器场所或经常添加或删除服务器非常有用
- 支持权重动态调整,大权重时被调度的概率更大
例:
listen web
balance random
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 3 check inter 3000 fall 2 rise 5
其他算法:
其它算法即可作为静态算法,又可以通过选项成为动态算法
大部分都是通过设置取模法(静态算法)或者设置一致性hash法(动态算法)实现动静切换的
取模法不支持动态调整权重,一致性hash法支持
source算法:
源地址hash,把同一个客户端请求发给同一个处理的后端主机,默认是静态方式,可以通过:hash-type选项修改
一般用于不插入cookie的tcp模式下使用,也可以给拒绝会话cookie的客户提供最好的会话粘性,适用于要想实现session会话保持但不支持cookie和缓存的场景
两种转发客户端请求到后端服务器的方式:
- 取模法
- 一致性hash法
map-base取模法:
- 对源ip进行hash,再根据总的权重取模。最终结果决定将此请求转发至对应的后端服务器
- 缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变
- 此方法是静态的,即不支持在线调整权重,不支持慢启动,只能动态上线和下线
hash-type 指定的默认值为此算法,计算式为:
hash(源ip)%后端总的权重。如:10%7=3
例:
listen web
balance source
hash-type map-base
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 1 check inter 3000 fall 2 rise 5
consistent一致性hash算法:
- 当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动
- hash环上,每个后端的权重是几,在环上就有几个点,同一个后端的hash点可能是散列的,点与点之间就是存放一致性hash后的数据,所以每次增加主机或减少主机,只会丢失点与点之间的数据,并不会全部丢(nginx的一致性hash算法也是这个)
- 该hash算法是动态的,支持使用socat等工具进行在线权重调整,支持慢启动
hash环偏斜问题解决办法:
- 如:A权重为1、B为2、C为3,环上可能是A有100个点,B有200个点,C有300个点,数据丢失时,只会丢失部分如:C300到A1的
例:
listen web
balance source
hash-type consistent
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 3 check inter 3000 fall 2 rise 5
uri算法:
- 对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器(也就是对同一个uri访问,调度到同一个后端)。适用于后端是缓存服务器场景
- 默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash
注意:
- 此算法基于应用层,所以只支持 mode http ,不支持 mode tcp
例:
默认对uri(域名左边)取模或一致性hash
listen web
balance uri
#hash-type map-base
hash-type consistent
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 3 check inter 3000 fall 2 rise 5
url_param算法:
- 对用户请求的url中的params部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器
- 通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server(另一种会话保持的方法),如果无没key,将按roundrobin算法
- 取模法和一致性hash实现动静算法切换
假设:
url = http://www.hj.com/foo/index.php?key=value
则:
host="www.hj.com"
url_param="key=value"
例: 取模法
对http://www.hj.com/index.php?user=1 和user=2测试
#haproxy算法配置
listen web
balance url_param user
hash-type map-base
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 1 check inter 3000 fall 2 rise 5
#测试访问
curl 2.2.2.25/ts1.html?user=1
curl 2.2.2.25/ts2.html?user=1
curl 2.2.2.25/ts1.html?user=2
hdr算法:
- 根据每个http的请求头部中的指定字段做hash,如果有值会被取出来做hash计算,然后根据总权重取模后发往某后端;如果没有值,则会使用默认的轮询调度
- 取模法和一致性hash实现动静算法切换
例: 一致性hash法,根据不同客户端类型调度或server name
#配置调度算法
listen web
balance hdr(User-Agent)
server web1 1.1.10:80 weight 1 check inter 3000 fall 2 rise 5
server web2 1.1.20:80 weight 1 check inter 3000 fall 2 rise 5
#测试访问
curl -A "Firefox" 2.2.2.25 #-A模拟客户端浏览器,火狐请求
curl -A "ie" 2.2.2.25 #ie浏览器请求
curl -A "chrome" 2.2.2.25 #谷歌浏览器请求
rdp-cookie算法:
- 对windows的远程桌面(rdp协议)负载调度,使用cookie会话保持,默认静态取模法
- 取模法和一致性hash实现动静算法切换
- rdp协议对应的端口是3389
例1: 一致性hash法调度
需要准备2台windows
实现rdp协议转发可以有多种,比如DNAT、nginx、lvs
listen web
bind 2.2.2.25:3389
balance rdp-cookie
hash-type consistent
server rdp1 1.1.10:3389 weight 1 check inter 3000 fall 2 rise 5
server rdp2 1.1.20:3389 weight 1 check inter 3000 fall 2 rise 5
例2: 基于iptables的nat转发调度,不建议使用,博主只是演示一下
haproxy主机必须开启ip_forward
#开启网络转发的内核参数
sysctl -w net.ipv4.ip_forward=1
#场景1: 处于两个网段时,后端win的网关要指向haproxy地址
iptables -t nat -A PREROUTING -d 1.0.0.0/8 -p tcp --dport 3389 -j DNAT --to-destination 1.1.1.10:3389
#场景2: 同一网段,要做dnat和snat
iptables -t nat -A PREROUTING -d 1.1.1.25 -p tcp --dport 3389 -j DNAT --to-destination 1.1.1.10:3389
iptables -t nat -A POSTROUTING -s 1.0.0.0/8 -j SNAT --to-source 1.1.1.25

浙公网安备 33010602011771号