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)

测试修改权重后的访问结果

impala负载均衡haproxy haproxy 负载均衡算法_linux

五、十种算法总结以及使用场景

静态:
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连接并发送数据。

impala负载均衡haproxy haproxy 负载均衡算法_linux_02

6.2 七层负载

七层负载均衡服务器起了⼀个反向代理服务器的作⽤,服务器建⽴⼀次TCP连接要三次握⼿,⽽client要访问webserver要先与七层负载设备进⾏三次握⼿后建⽴TCP连接,把要访问的报⽂信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握⼿与此台webserver建⽴TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。

impala负载均衡haproxy haproxy 负载均衡算法_impala负载均衡haproxy_03

七、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" ';