HAProxy作为一款轻量级的负载均衡器,所以负载均衡策略是非常重要的。今天我们就来对几种常见的策略进行测试,这样我们方便我们真正理解和掌握。
利用Docker+Tomcat+HAProxy搭建一套测试集群环境请参考前文。
什么是负载均衡策略
负载均衡就是在Client和Server之间多加了一层。
何为策略(或者说算法)?用户发来的请求,HAProxy应该转发给哪一台server呢?选择哪一台server的策略,就是负载均衡策略。
比如HAProxy可以随便挑一台来接收请求,或者server1 server2 server3轮流接收请求。
这里说的"随便"就是负载均衡策略中的random
这里说的"轮流"就是负载均衡策略中的roundrobin
配置负载均衡策略
HAProxy中配置负载均衡策略非常简单。甚至我们不配置,默认使用的就是轮询了。
只需要在backend中加上"balance roundrobin"即可。
backend servers
balance roundrobin
server tomcat1 127.0.0.1:8081
server tomcat2 127.0.0.1:8082
server tomcat3 127.0.0.1:8083
格式为:balance <algorithm> [ <arguments> ]
常见的策略有:
- roundrobin
- static-rr
- leastconn
- source
- url_param
- uri
- hdr(<name>)
- random
- rdp-cookie
常用负载均衡策略
1. roundrobin 轮询
这个非常简单,顾名思义就是按照server列表,按server1、server2、server3的顺序轮流来接收请求。
这个也是HAProxy的默认策略,我们不配置"balance roundrobin",使用的也是轮询策略。
backend servers
balance roundrobin
server tomcat1 127.0.0.1:8081
server tomcat2 127.0.0.1:8082
server tomcat3 127.0.0.1:8083
weight 权重
其实还有一个参数,weight权重。
如果我们配置server的weight,轮询还是1 2 3吗?
backend servers
balance roundrobin
server tomcat1 127.0.0.1:8081 weight 1
server tomcat2 127.0.0.1:8082 weight 2
server tomcat3 127.0.0.1:8083 weight 3
上面我们给server1/2/3的权重分别是1 2 3,表示server3的权重是最大的,server1的权重是最小的。
意思是,更优先选择server3.
修改haproxy.cfg的配置为上面所示,我们连续发送请求,观察一下轮询下的负载均衡。
Server 3
Server 2
Server 3
Server 1
Server 3
Server 2
Server 3
Server 2
Server 3
Server 1
Server 3
Server 2
可以看到12次请求中,server1被访问6次,server2被访问4次,server1被访问2次。
这个比例刚好和server的权重比是一致的!!!
如果没有指定server的权重,那么他们的weight都是相等的,所以默认下是server1 server2 server3(这里不是按数字大小,而是server列表中前后顺序)的轮流接收请求。
2. static-rr 静态轮询
看了很多文章,这个策略都是一笔带过,基本就是翻译了官方文档。于是怀着好奇的心理,深入了解了一下这个策略。
先看名字,static就是静态的意思,rr就是roundrobin,组合起来,就是静态轮询的意思。
既然它叫静态轮询,那么我们默认的roundrobin就是动态轮询喽,dynamic roundrobin。
轮询好理解,就是你我他一个个排着队接收请求。
那么静态和动态是啥意思呢。
官方文档:
It is static, which means that changing a server's weight on the fly will have no effect.
官方说了,也就是在运行时修改server的权重是无效的。本文前面roundrobin中说过,权重会影响轮询。
那就涉及haproxy运行过程中修改权重了。
本系列的第六篇就到如何运行时修改server的权重《HAProxy快速入门(六)—— 管理HAProxy》
用socat连接socket,在执行命令:
set server servers/tomcat1 weight 10
这样我们就修改了server的权重了。
我们先把负载均衡策略改成静态轮询:
然后我们重启haproxy:
service haproxy restart
默认下配置下,我们没有给server声明权重,所以默认权重是1. 我们可以用命令查询一下:
可以看到,默认权重都是1
接下来,我们修改tomcat1的权重,我们把权重修改成2:
非常遗憾,命令行提示backend的静态负载策略就能把权重设置成0%或者100%。
为什么能设置成0%和100%呢?那是因为设置0%时,就相当于把这台server禁用掉。如果设置成100%就相当于启用它。
我们不妨来测试一下:
访问http://localhost/,我们会发现请求不到server1了,我们交替访问server2和server3.
设置成weight 100,就能访问到了,这里不一一演示了。
但是如果我们用的是roundrobin,就可以动态修改server的权重。这就是static rr和roundrobin的区别!
3. leastconn 最少连接数
这个比较好理解,当前多个服务器之中,选择接收连接最少的那台服务器,也就是最闲的那台服务器。这样保证不会涝的涝死,旱的旱死。
如果有多台是相同负载呢?这时候就在它们之间用轮询策略。总之要保证大家都有活干。
客户端和服务端的连接是长连接时比较有效。因为短连接很快就结束了,可能请求一直进来,很快结束,导致出现一直是一台服务器处理请求的情况,其他服务器都空闲着。你细品。
这个负载策略测试需要并发才要体现,所以这里不便演示。
4. source 源IP
这种策略会对源IP做散列,好处是同一个IP会一直访问同一台server。
我们修改负载均衡策略成source
然后重启haproxy后。
访问http://localhost,不管访问100次还是一万次,我们始终访问的是server1(当然不一定是server1,但可以肯定是同一台server)。
我是在PC上访问访问的是server1,因为我的HAProxy是部署在虚拟机中,所以直接在CentOS访问时 curl http://localhost,得到的结果一直是server3.
5. url_param URL参数
格式:balance url_param <param> [check_post]
我们会在负载均衡策略中声明一个参数,然后haproxy将会对参数值做hash,然后路由到某一台服务器。
所以相同参数会始终访问同一台服务器。
本例中,我们声明一个“app”的参数
backend servers
balance url_param app
server tomcat1 127.0.0.1:8081
server tomcat2 127.0.0.1:8082
server tomcat3 127.0.0.1:8083
我们访问:http://localhost?app=app1会发现一直访问的是某一台服务器。如果改变其他的参数,也是始终访问同一台服务器。
6. url URL
这种策略会对URL路径做散列。
注意我们的URL通常包括两部分,第一部分是URL前部分,通常是/分隔的,后部分是参数,也就是从问号开始
所以url负载均衡策略也考虑到了这两种情况:
- 如果配置:balance url,将对问号前的url做hash,所以相同的不带参数的url会始终访问同一台服务器。
- 如果配置:balance url whole,将会完整的url做hash,完全相同的url才会始终访问同一台服务器。
还有两个额外的参数可以配置:
- depth:深度,如果指定深度,则会对指定层级的URL路径做hash,每个斜杠就是一层,如http://localhost/web/pic/food/....
- len:长度,如果指定一个长度,则会对截取后的URL做hash
7. hdr(<name>) header
hdr是header的简写。
指定一个header,对每个请求的header做hash,和前面一样的道理。带了相同header的的请求会被指定到同一台服务器。
我们来测试一下。
backend servers
balance hdr(flag)
server tomcat1 127.0.0.1:8081
server tomcat2 127.0.0.1:8082
server tomcat3 127.0.0.1:8083
为了测试方便编辑header,我们使用postman作为httpclient。
测试发现,只要我们的请求中带了flag这个header,他的值是相等的话,就会一直访问一台服务器。
如果request没有带这个header,则会使用轮询。
8. random 随机
这个就不用多说了,随机选择一台。
9. rdp-cookie
对会cookie做散列,相同cookie的请求会被路由到同一服务器。
这种策略有个好处,很方便把相同用户(session id一样)的请求发送到同一台服务器。