HAProxy的调度算法分为静态调度算法、动态调度算法和其他调度算法
静态算法:按照事先定义好的规则轮询公平调度,不关⼼后端服务器的当前负载、链接数和响应速度等,且⽆法实时修改权重,只能靠重启HAProxy⽣效。
动态算法:基于后端服务器 状态进⾏调度适当调整,⽐如优先调度⾄当前负载较低的服务器,且权重可以在haproxy运⾏时动态调整⽆需重启。
其他算法:即可作为静态算法,⼜可以通过选项成为动态算法
一、静态调度算法
1.1 static-rr
在listen或backend区域配置
balance static-rr
基于权重的轮询调度,不⽀持权重的运⾏时调整及后端服务器慢启动,其后端主机数量没有限制。weight默认为1。
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http/tcp
log global
balance static-rr
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 2 check inter 3000 fall 2 rise 5
1.2 first
在listen或backend区域配置
balance first
根据服务器在列表中的位置,⾃上⽽下进⾏调度,但是其只会当第⼀台服务器的连接数达到上限,新请求才会分配给下⼀台服务,因此会忽略服务器的权重设置。
如果有maxconn,则匹配maxconn的最大值。
listen web_host
bind 192.168.7.101:80,:8801-8810,192.168.7.101:9001-9010
mode http/tcp
log global
balance first
server web1 192.168.7.103:80 maxconn 2 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
二、动态调度算法
2.1 roundrobin
在listen或backend区域配置,该算法为默认算法
balance roundrobin
基于权重的轮询动态调度算法,可以使用socat动态调整权重。
HAProxy的roundrobin轮询模式不完全等于LVS的RR轮训模式,区别在于
①HAProxy中的roundrobin⽀持慢启动,新加的服务器会逐渐增加转发数;
②HAProxy每个后端backend中最多⽀持4095个real server;
③HAProxy⽀持对real server权重动态调整;
listen web_host
bind 192.168.7.101:80
mode http/tcp
log global
balance roundrobin
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 2 check inter 3000 fall 2 rise 5
2.2 leastconn
在listen或backend区域配置,该算法为默认算法
balance leastconn
当前后端服务器连接最少的优先调度。
①支持加权的最少连接
②支持动态调整权重
③支持慢启动
listen web_host
bind 192.168.7.101:80
mode http/tcp
log global
balance leastconn
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 2 check inter 3000 fall 2 rise 5
三、其他调度算法
3.1 source
源地址hash,基于⽤户源地址hash并将请求转发到后端服务器。
第一种,默认为静态即取模⽅式;
第二种,可以通过hash-type⽀持的选项更改,动态即hash一致方式。
3.1.1 source之map-base取模法
在listen或backend区域配置
mode http/tcp
balance source
取模法,基于服务器总权重的hash数组取模。
不⽀持在线调整权重;
不⽀持慢启动;
缺点:当服务器的总权重发⽣变化时,即有服务器上线或下线,都会因权重发⽣变化⽽导致调度结果整体改变。
例如,后端有三台服务器,每台服务器权重都为1,则总权重为3,haproxy给源地址做hash计算,hash_value%3。其中获取的值如果为0,发给第一台服务器;如果为1,发给第二台服务器;如果为2,发给第三台服务器。如果一台服务器坏掉了,其要在通过hash_value%3计算,因权重发⽣变化⽽导致调度结果整体改变。
3.1.2 source之一致hash法
在listen或backend区域配置
mode http/tcp
balance source
hash-type consistent
⼀致性哈希,该hash是动态的。
⽀持在线调整权重;
⽀持慢启动;
优点:当服务器的总权重发⽣变化时,对调度结果影响是局部的,不会引起⼤的变动。
使用场景:在没有做session共享的情况下,想做会话保持。
3.2 uri
基于对⽤户请求的uri做hash并将请求转发到后端指定服务器。
3.2.1 uri之map-base取模法
在listen或backend区域配置
mode http
balance uri
3.2.2 uri之一致hash法
在listen或backend区域配置
mode http
balance uri
hash-type consistent
3.3 url_param
url_param对⽤户请求的url中的params部分中的参数name(key)作hash计算,并由服务器总权重相除以后派发⾄某挑出的服务器。
url = http://www.magedu.com/foo/bar/index.php?k1=v1&k2=v2
所以:
host = "www.magedu.com"
url_param = "k1=v1&k2=v2"
3.3.1 uri之map-base取模法
在listen或backend区域配置
# curl http://192.168.7.101/app/index.html?name=NAME #单个参数访问
mode http
balance url_param name
# curl http://192.168.7.101/app/index.html?age=AGE
mode http
balance url_param age
# curl http://192.168.7.101/app/index.html?age=AGE&&name=NAME #多个参数访问
mode http
balance url_param name,age
3.3.2 uri之一致hash法
在listen或backend区域配置
# curl http://192.168.7.101/app/index.html?name=NAME #单个参数访问
mode http
balance url_param name
hash-type consistent
# curl http://192.168.7.101/app/index.html?age=AGE
mode http
balance url_param age
hash-type consistent
# curl http://192.168.7.101/app/index.html?age=AGE&&name=NAME #多个参数访问
mode http
balance url_param name,age
hash-type consistent
3.4 hdr
针对⽤户每个http头部(header)请求中的指定信息做hash,此处由name指定的http⾸部将会被取出并做hash计算,然后由服务器总权重相除以后派发⾄某挑出的服务器,假如⽆有效的值,则会使⽤默认的轮询调度。
3.4.1 hdr之map-base取模法
在listen或backend区域配置
mode http
balance hdr(User-Agent)
举例:对header里的User-Agent字段(浏览器类型)做hash计算,同一个浏览器访问后端同一个服务器。
3.4.2 hdr之一致hash法
在listen或backend区域配置
mode http
balance hdr(User-Agent)
hash-type consistent
3.5 rdp-cookie
服务器端的rdp-cookie使⽤客户端的cookie保持会话,可以实现对windows远程桌⾯(一般后端服务器为windows server)的负载等。
3.5.1 rdp-cookie之map-base取模法
在listen或backend区域配置
listen RDP
bind 10.0.0.17:3389
mode tcp
balance rdp-cookie
persist rdp-cookie #启用基于rdp-cookie的持久连接,同一个cookie就转发给对应的服务器
tcp-request inspect-delay 5s #设置内容检查期间等待数据的最大允许时间
tcp-request context accept if RDP_COOKIE #匹配RDP_COOKIE存在就接受请求
server windows-server1 10.0.0.13:3389 check fall 3 rise 5 inter 2000
3.5.2 rdp-cookie之一致hash法
在listen或backend区域配置
listen RDP
bind 10.0.0.17:3389
mode tcp
balance rdp-cookie
hash-type consistent
persist rdp-cookie #启用基于rdp-cookie的持久连接,同一个cookie就转发给对应的服务器
tcp-request inspect-delay 5s #设置内容检查期间等待数据的最大允许时间
tcp-request context accept if RDP_COOKIE #匹配RDP_COOKIE存在就接受请求
server windows-server1 10.0.0.13:3389 check fall 3 rise 5 inter 2000
3.6 random
在1.9版本开始增加⼀个叫做random的负载平衡算法,其基于⼀个随机数作为⼀致性hash的key,随机负载平衡对于⼤型服务器场或经常添加或删除服务器⾮常有⽤。
3.6.1 random之map-base取模法
在listen或backend区域配置
listen web_host
bind 192.168.7.101:80
mode http/tcp
log global
balance random
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
3.6.2 random之一致hash法
在listen或backend区域配置
listen web_host
bind 192.168.7.101:80
mode http/tcp
log global
balance random
hash-type consistent
server web1 192.168.7.103:80 weight 1 check inter 3000 fall 2 rise 5
server web2 192.168.7.104:80 weight 1 check inter 3000 fall 2 rise 5
四、使用socat动态调整HAProxy后端服务器权重
安装socat
yum install socat -y
查看socat的帮助命令
echo "help" | socat stdio /var/lib/haproxy/haproxy.sock
常用命令
disable server : disable a server for maintenance (use 'set server' instead)
enable server : enable a disabled server (use 'set server' instead)
get weight : report a server's current weight
set weight : change a server's weight (deprecated)
show info : report information about the running process [desc|json|typed]*
查看haproxy信息
echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock
haproxy配置文件
listen lck-net-80
bind 10.0.0.17:80
mode http
option forwardfor
log global
server web1 10.0.0.13:80 weight 1 check inter 3000 fall 2 rise 5
server web2 10.0.0.14:80 weight 2 check inter 3000 fall 2 rise 5
使用socat查看server权重
[root@centos7 ~]# echo "get weight lck-net-80/web1" | socat stdio /var/lib/haproxy/haproxy.sock
1 (initial 1)
[root@centos7 ~]# echo "get weight lck-net-80/web2" | socat stdio /var/lib/haproxy/haproxy.sock
2 (initial 2)
使用socat修改server权重
[root@centos7 ~]# echo "set weight lck-net-80/web1 4" | socat stdio /var/lib/haproxy/haproxy.sock
[root@centos7 ~]# echo "get weight lck-net-80/web1" | socat stdio /var/lib/haproxy/haproxy.sock
4 (initial 1)
测试修改权重后的访问结果
五、十种算法总结以及使用场景
静态:
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动态调整权重、支持慢启动功能。
六、四层负载与七层负载
6.1 四层负载
在四层负载设备中,把client发送的报⽂⽬标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建⽴TCP连接并发送数据。
6.2 七层负载
七层负载均衡服务器起了⼀个反向代理服务器的作⽤,服务器建⽴⼀次TCP连接要三次握⼿,⽽client要访问webserver要先与七层负载设备进⾏三次握⼿后建⽴TCP连接,把要访问的报⽂信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握⼿与此台webserver建⽴TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。
七、IP透传
7.1 TCP负载IP透传
负载均衡haproxy配置
listen web_prot_http_nodes
bind 192.168.7.101:80
mode tcp
balance roundrobin
server web1 blogs.studylinux.net:80 send-proxy check inter 3000 fall 3 rise 5
后端服务器Nginx配置
server {
listen 80 proxy_protocol;
server_name blogs.studylinux.net;
......
PROXY 协议允许 Nginx 和 Nginx Plus 接受来自代理服务器和负载平衡器的客户端连接信息,比如 HAproxy 和 Amazon Elastic Load Balancer (ELB) 。
通过 PROXY 协议,Nginx 可以从 HTTP,SSL,HTTP / 2,SPDY,WebSocket 和 TCP 中获取到源 IP 地址。获取到客户端的源 IP 地址,可以在为网页指定语言、设置 IP 黑名单或只是简单的日志和统计分析。
通过 PROXY 协议传输的数据是客户端的 IP 地址、代理服务器的 IP 地址和所有的端口号。
7.2 HTTP负载IP透传
负载均衡haproxy配置
defaults
option forwardfor
或者:
option forwardfor header X-Forwarded-xxx
#option forwardfor则后端服务器web格式为X-Forwarded-For
#⾃定义传递IP参数,后端web服务器写X-Forwarded-xxx,
7.3 web服务器⽇志格式配置
apache
LogFormat "%{X-Forwarded-For}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
tomcat
pattern='%{X-Forwarded-For}i %l %T %t "%r" %s %b "%{User-Agent}i"'/>
nginx
log_format main '"$http_x_forwarded_For" - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" ';