文章目录
- 前言
- 介绍
- 静态算法
- static-rr
- first
- 动态算法
- roundrobin
- leastconn
- 其他算法
- source算法
- map-base 取模法
- 一致性hash
- uri
- urI_param 取模法
- hdr
- 总结
- 本文相关连接如下:
前言
本文相关连接如下:
- 如果想更多了解haproxy的相关知识,请点击:一站式带你深入了解HAProxy
- 如果想深入探讨haproxy的高级用法,请移步:进阶!haproxy高级功能与配置
介绍
HAProxy算法是为了实现高可用性、负载均衡以及基于TCP和HTTP的应用程序代理而设计的。HAProxy是一个使用C语言编写的自由及开放源代码软件,特别适用于那些负载特大的web站点,这些站点通常需要会话保持或七层处理。
HAProxy实现了一种事件驱动、单一进程模型,这种模型支持非常大的并发连接数。
- HAProxyi通过固定参数balance指明对后端服务器的调度算法
- balance参数可以配置在Elisten或backendi选项中。
- HAProxy的调度算法分为静态和动态调度算法
- 有些算法可以根据参数在静态和动态算法中相互转换。
静态算法
静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度等,且无法实时修改权重(只能为0和1,不支持其它值),只能靠重启HAProxy生效。
static-rr
static-rr 基于权重的轮询调度
- 不支持运行时利用s0ct进行权重的动态调整(只支持0和1,不支持其它值)
- 不支持端服务器慢启动
- 其后端主机数量没有限制,相当于LVS中的wrr
慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
不可更改体现:
验证:
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
first
- 根据服务器在列表中的位置,自上而下进行调度
- 其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务
- 其会忽略服务器的权重设置
- 不支持用soct进行动态修改权重,可以设置0和1,可以设置其它值但无效
配置:
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
如果需要看效果,需要在两台主机上进行死循环,并设置最大连接数为1、
输出效果:
[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
更改效果并没有成功,权重优先级低
动态算法
- 基于后端服务器状态进行调度适当调整,
- 新请求将优先调度至当前负载较低的服务器
- 权重可以在haproxyi运行时动态调整无需重启
roundrobin
打在负载小的主机上,先看负载,再看权重
- 基于权重的轮询动态调度算法
- 支持权重的运行时调整,不同于引vs中的r轮训模式
- HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数)
- 其每个后端backend中最多支持4095个server
- 支持对real server权重动态调整
- roundrobin为默认调度算法,此算法使用广泛
配置:
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
验证:
[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
可以修改权重,但是权重都是2的情况下,因为负载优先,所以两个主机轮流上线
leastconn
- leastconn加权的最少连接的动态
- 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
- 比较适合长连接的场景使用,比如:MySQL等场景。
打在链接数少的主机上,先看链接数,后看权重
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
注意:此处web2的权重,也就是20服务器权重为2,理应访问两次20主机,一次10主机,但因为算法是leastconn,因此效果变成了连接数优先,10和20主机轮番上线
连接与权重验证:
[root@haproxy ~]# echo "set weight webcluster/web1 3" | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
即使权重修改成功,但是连接优先级更高
其他算法
其它算法即可作为静态算法,又可以通过选项成为动态算法
source算法
源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端wb服务器。
此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,很多会话将丢失,默认为静态方式,
如果访问客户端时一个家庭,那么所有的家庭的访问流量都会被定向到一台服务器,这时source算法的缺陷
缺点:同一家公司主机出去的IP是同一个,同一家访问会导致负载超和
解决方法:取模法和一致性hash
- 可以通过hash-type支持的选项更改这个算法,一般是在不插入Cookiel的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
表现为流量只流向同一台服务器:
map-base 取模法
- map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。
- 此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度
- 缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type指定的默认值为此算法
- 所谓取模运算,就是计算两个数相除之后的余数,10%7=3,7%4=3
- map-based算法:基于权重取模,hash(source_.ip)%所有后端服务器相加的总权重
如果权重改变,则has偏移,导致服务器上下线,会导致会话丢失
配置:
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
实际操作验证:
正常访问情况:
当权重发生改变时,只能修改配置文件,因为不支持在线调整权重
100主机访问的服务器由原先的20变为10
10主机由原先的20服务器变为10服务器
只有20主机访问的还是原先的10服务器
总结:map-base 取模法当总权重发生改变,将引起会话连接的大面积改变
一致性hash
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动
该hash算法是动态的,支持使用socats等工具进行在线权重调整,支持慢启动
- 后端服务器哈希环点keyA=hash(后端服务器虚拟ip)%(2^32)
- 客户机哈希环点keyl=hash(c1ient_ip)%(2A32) 得到的值在[0–4294967295]之间,
- 将keyA和keyl都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器
hash环流程图:
-
得到的IP是0到2^32-1之间
-
为什么要减1:从0开始,所以要减1
客户端hash链接顺时针旋转,寻找最近的第一个服务器,如果第一个服务器关闭,则继续顺时针寻找下一个最近的服务器
面试:什么叫hash环
- hash环是一个0到2^32-1的一个数字被落到一个圆上,这个圆就叫hash环
- 取模法: 对服务器IP和hash环的总数进行取模,是多少就落到上面
余数不会超过hash环的数量,最多2^32-1
后端服务器在线调度方式图解:
后端服务器离线调度方式图解:
hash一致性特点:即使权重改变或服务器下线,但是我该到的服务器没问题则还是到哪,不会发生服务器偏移
配置:
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
[root@haproxy ~]# for i in {1..10}; do curl 172.25.254.100; done
验证:
正常运行下
100主机访问的服务器是20
10主机访问的服务器是10
20主机访问的服务器是10
当权重发生改变时
100主机访问的服务器还是20
10主机访问的服务器是10
20主机访问的服务器是10
当某个服务器下线(此处是10服务器下线),就会寻找下一个主机,原先是谁就还是访问谁,此处博主因为只开了两个服务器,效果并不明显,想效果更明显的小伙伴可以多开几台服务器
uri
- 基于对用户请求的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>scheme:协议http
user:用户
password:密码
host:主机名
port:端口
path:文件路径/index.htmlparams:向服务器传递的指令,如Search
?代表
params:搜索的字段
frag:片段(在文件里面做一个索引,快速定位你点击的片段)
params例子:
uri与url图例
- URI = Uniform Resource Identifier 统一资源标志符
- URL = Uniform Resource Locator 统一资源定位符,资源的真实位置
- URN = Uniform Resource Name 统一资源名称,只指定到资源名称,没有资源的文件
向服务器添加网页:
访问的uri不变,访问的地址就不变
urI_param 取模法
url_param 对用户请求的 url 中的 params 部分中的一个参数 key 对应的 value 值作 hash计算,并由服务器 总权重相除以后派发至某挑出的服务器 ,后端搜索同一个数据会被调度到同一个服务器,多用与电商,通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server
如果无没 key ,将按 roundrobin 算法
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
#添加
listen webclusterbind *:80mode httpbalance url_param name,userid #支持对多个url_param hashhash-type consistentserver web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 1server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 2
搜索同一个东西,会调度到同一个服务器上
hdr
-
针对用户每个http头部(header)请求中的指定信息做hash,
-
此处由 name 指定的 http 首部将会被取出并做 hash计算,
-
然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
[root@haproxy ~]# systemctl restart haproxy.service
验证:
总结
静态算法
static-rr--------->tcp/http 不支持动态更改,根据权重的轮询算法,服务器的权重越高,被分配到的请求就越多。
first------------->tcp/http 不支持动态更改,只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务
动态算法
roundrobin-------->tcp/http 它将清求轮流分配到各服务器上,此算法对于服务器的负载能力是均衡的。
leastconn--------->tcp/http 优先连接数,这是最少连接数算法,它会根据服务器当前的连接数和队列长度来决定是否分配新的连接
以下静态和动态取决于hash_type是否consistent
source------------>tcp/http ,基于清求来源P的算法,它会把来自同IP的请求分配到同一个服务器
Uri--------->http 基于请求的URI进行hash运算,然后根据得到的hash值选择服务器
urI_param--------->http 基于URL参数的算法,可以指定参数名,然后根据参数值的hash值来选择服务器
hdr–------->http 基于HTTP请求头来的算法,可以指定头名,然后根据头值的hash来选择服务器
各算法应用场景
first #使用较少
static-rr #做了session共享的web集群
roundrobin #任务调试,产品测试
leastconn #数据库
本文相关连接如下:
一站式带你深入了解HAProxy
进阶!haproxy高级功能与配置
- 如果想更多了解haproxy的相关知识,请点击:一站式带你深入了解HAProxy
- 如果想深入探讨haproxy的高级用法,请移步:进阶!haproxy高级功能与配置