天天看点

haproxy里的超时配置and负载均衡

一,haproxy 里的超时

客户端请求阶段

timeout client
    haproxy 和客户端通信时,连接不活跃的时间,既不发送数据,也不ack接收的数据
    如果未设置,则永不超时,此时连接是否超时依赖于tcp连接本身的机制
timeout http-request
    tcp 连接建立后,直到所有头部发送完毕的时间
    如果未设置,则使用 timeout client 的值
    如果 frontend 是 tcp 模式,则使用 backend 中的 timeout http-request
timeout http-keep-alive
    当开启 option http-keep-alive 时,haproxy 处理完请求 A ,等待连接上请求 B ,请求 A 结束到请求 B 开始之间的间隔时间
    如果未设置,则使用 timeout client
    如果 frontend 是 tcp 模式,则使用 backend 中的 timeout http-keep-alive
timeout client-fin
    当客户端和 haproxy 的连接的一端已经 shutdown 时,该连接不活跃的时间
    如果未设置
        非隧道连接,使用 timeout client
        隧道连接,如 RDB/WebSocket ,使用 timeout tunnel
           

haproxy 转发阶段

timeout queue
    当 haproxy 接受客户端请求后,如果暂时找不到可以立即转发的后端,此时会将该连接放置在 backend 或者 server 的请求队列中,等待有 server 可以处理请求时,就转发过去
    timeout queue 指定的是,某个请求被放置在队列中的最大时间,如果超时,则认为该请求不能被处理,返回 503 给客户端
    如果未设置,则使用 timeout connect
timeout connect
    haproxy 和后端建立 tcp 连接的超时时间
    如果未设置则永不超时
           

后端响应阶段

timeout server
    haproxy和后端通信时,连接不活跃的时间,即既不发送数据,也不 ack 接收的数据
timeout server-fin
    当 haproxy 和后端的连接的一端已经 shutdown 时,该连接不活跃的时间
    如果未设置
        非隧道连接,使用 timeout server
        隧道连接,使用 timeout tunnel
           

特殊场景

timeout tunnel
    隧道连接的场景
        http 连接升级后 WebSocket 之后
        转发 CONNECT 请求 给http 代理
        tcp 连接
    隧道连接建立后,该连接双向不活跃的时间,即连接上既不发送数据,也不接收数据
    当连接转换为隧道连接后,timeout client/timeout server 都将被 timoeut tunnel 取代

timeout tarpit
    当 http 请求被 http-request tarpit 指令标记后,haproxy 会将连接维持 timeout tarpit 的时间,如果超时后,该连接仍然未关闭,就回复 500 响应码给客户端,参看 http-request tarpit 的说明
           

二,配置负载均衡策略

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 [ ]

常见的策略有:

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 [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() 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的请求会被路由到同一服务器。

继续阅读