HAProxy调度算法:

HAProxy通过固定参数balance指明对后端服务器的调度算法,该参数可以配置在listen或backend选项中。HAProxy的调度算法分为静态和动态调度算法,但是有些算法可以根据参数在静态和动态算法中相互转换。

一、静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能靠重启HAProxy生效。
1.first
根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置,此方式使用较少。如果需要人为指定 id,则可以在server server_name ip:port指令后面加上id <idnumber>id 号必须是正整数。

2.static-rr
基于权重进行轮叫,与roundrobin类似,但是为静态方法,在运行时调整其服务器权重不会生效;不过,其在后端服务器连接数上没有限制;不支持慢启动,在高负荷的情况下,服务器重新上线时会立即被分配大量连接。(相当于LVS中的 wrr)

例
listen zzhz
    bind 192.168.80.110:81 #IP地址
    mode http
    log global
#   balance static-rr
    balance first
    server web1 192.168.80.110:80 weight 3 check inter 3000 fall 2 rise 5
    server web2 192.168.80.120:80 weight 1 check inter 3000 fall 3 rise 5

#first静态算法
[root@localhost7e ~]# while  true;do  curl http://192.168.80.110:81/index.html ; sleep 0.1;done
192.168.80.110
192.168.80.110
192.168.80.110
192.168.80.110
#static-rr静态算法
[root@localhost7e ~]# while  true;do  curl http://192.168.80.110:81/index.html ; sleep 0.1;done
192.168.80.110
192.168.80.110
192.168.80.110
192.168.80.120
192.168.80.110
192.168.80.110
192.168.80.110
192.168.80.120

 

二、动态算法:基于后端服务器 状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。
1.roundrobin(默认)
基于权重进行轮叫,在服务器
的处理时间保持均匀分布时,这是最平衡、最公平的算法。此算法是动态的,这表示其权重可以在运行时进行调整,不过,在设计上,每个后端服务器仅能最多接受4128个连接,roundrobin不完全等于lvs中的rr轮训模式,HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),其每个后端backend中最多支持4095个real server。roundrobin为默认调度算法.
 
2 leastconn(WLC)
加权的最少连接的动态,适用于长连接的会话,新的连接请求被派发至具有最少连接数目的后端服务器;在有着较长时间会话的场景中推荐使用此算法,如LDAP、SQL等,其并不太适用于较短会话的应用层协议,如HTTP;此算法是动态的,可以在运行时调整其权重;

3.random:
在1.9版本开始增加一个叫做random的负载平衡算法,其基于一个随机数作为一致性hash的key,随机负载平衡对于大型服务器场或经常添加或删除服务器非常有用。支持weight的动态调整,weight较大的主机有更大概率获取新请求.

例
listen zzhz
    bind 192.168.80.110:81 #IP地址
    mode http
    log global
    balance roundrobin
	#balance leastconn
	#balance  random
    server web1 192.168.80.110:80 weight 3 check inter 3000 fall 2 rise 5
    server web2 192.168.80.120:80 weight 1 check inter 3000 fall 3 rise 5

#roundrobin动态算法
[root@localhost7e ~]# while  true;do  curl http://192.168.80.110:81/index.html ; sleep 0.1;done
192.168.80.110
192.168.80.110
192.168.80.110
192.168.80.120
192.168.80.110
192.168.80.110
192.168.80.110
192.168.80.120
#调整权重
[root@localhost7B haproxy]# echo "get weight zzhz/web1" | socat stdio /var/lib/haproxy/haproxy.sock
3 (initial 3)
[root@localhost7B haproxy]# echo "set weight zzhz/web1 2" | socat stdio /var/lib/haproxy/haproxy.sock
[root@localhost7B haproxy]# echo "get weight zzhz/web1" | socat stdio /var/lib/haproxy/haproxy.sock
2 (initial 3)

[root@localhost7e ~]# while  true;do  curl http://192.168.80.110:81/index.html ; sleep 0.1;done
192.168.80.110
192.168.80.110
192.168.80.120
192.168.80.110
192.168.80.110
192.168.80.120

[root@localhost7B haproxy]# systemctl restart haproxy.service   #重启权重将按配置文件配置
[root@localhost7B haproxy]# echo "get weight zzhz/web1" | socat stdio /var/lib/haproxy/haproxy.sock
3 (initial 3)

  

三、其它算法:即可作为静态算法,又可以通过选项成为动态算法

科普内容:
map-based 取模法
使用map-based哈希方法时,哈希表(哈希的结果)是包含所有活动服务器的静态数组。该哈希方法会考虑服务器权重。但是在服务器运行时权重发生变化会被忽略。核心是按照服务器在数组中的位置来选择调度的服务器,所以当服务器有上线或者下线时,总权重会发生变化,哈希也就变化了,这会导致大部分的连接将会重新被调度到不同的服务器。这种调度算法不支持慢启动也不适合在使用缓存的场景使用。

consistent一致性哈希方法
使用 consistent 一致性哈希方法时,哈希表中每个服务器对应多个哈希值(这些对应于同一个服务器的哈希值和该服务器的名称或者 ID 有关联),这个哈希表使用树结构(某种数据结构)来组织。HAProxy 会在该树结构上查找哈希键,并选中最合适的值。
该哈希方法支持动态修改服务器权重,所以其支持慢启动。使用该调度策略的优势是,当某个服务器停用或者再次启用时,只有和该服务器相关的哈希信息会被移除。当某个服务器加入服务器组时,只有一部分连接会被重新分配,这使得一致性哈希方法是使用缓存时的理想调度策略。

1. source
源地址hash,再基于服务器总权重的取模,最终结果决定将此请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项更改。
这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景

1.1:map-base取模法:
将请求的源地址进行hash运算,并由后端服务器的权重总数相除后派发至某匹配的服务器;这可以使得同一个客户端IP的请求始终被派发至某特定的服务器;此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变,hash-type 指定的默认值为此算法
A.对原地址hash,第一次调度时使用WLC (所谓取模运算,就是计算两个数相除之后的余数,10%7=3, 7%4=3) 
B.基于权重取模,hash(source_ip)%所有后端服务器相加的总权重   

1.2:consistent一致性哈希:
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,hash(o)mod n ,该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动

	
	
2. uri
对URI的左半部分(“问题”标记之前的部分)或整个URI进行hash运算,并由服务器的总权重相除后派发至某匹配的服务器;这可以使得对同一个URI的请求总是被派发至某特定的服务器,除非服务器的权重总数发生了变化;此算法常用于代理缓存或反代理以提高缓存的命中率;需要注意的是,此算法仅应用于HTTP后端服务器场景;其默认为静态算法,不过也可以使用hash-type修改此特性;
注意:此算法是应用层,所有只支持 mode http ,不支持 mode tcp
1、key1=hash(source_ip)%(2^32)  [0---4294967295]
2、keyA=hash(后端服务器虚拟ip)%(2^32)
3、将key1和keyA都放在hash环上,将用户请求调度到离key1最近的keyA对应的后端服务器	

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
整个uri:/<path>;<params>?<query>#<frag>	
左半部分:/<path>;<params>	


3. url_param
通过<argument>为URL指定的参数在每个HTTP的GET请求中将会被检索;如果找到了指定的参数且其通过等于号“=”被赋予了一个值,那么此值将被执行hash运算并被服务器的总权重相除后派发至某匹配的服务器;此算法可以通过追踪请求中的用户标识进而确保同一个用户ID的请求将被送往同一个特定的服务器,除非服务器的总权重发生了变化;如果某请求中没有出现指定的参数或其没有有效值,则使用轮叫算法对相应请求进行调度;此算法默认为静态的,不过其也可以使用hash-type修改此特性;
假设:
url = http://www.magedu.com/foo/bar/index.php?key=value
则:
host = "www.magedu.com"
url_param = "key=value"

测试
curl http://192.168.80.110:81/index.html?name=NAME #单个参数访问 
curl http://192.168.80.110:81/index.html?age=AGE&&name=NAME #多个参数访问

4.hdr(<name>)
对于每个HTTP请求,通过<name>指定的HTTP首部将会被检索;如果相应的首部没有出现或其没有有效值,则使用轮叫算法对相应请求进行调度;其有一个可选选项“use_domain_only”,可在指定检索类似Host类的首部时仅计算域名部分(比如通过www.feiyu.com来说,仅计算feiyu字符串的hash值)以降低hash算法的运算量;此算法默认为静态的,不过其也可以使用hash-type修改此特性;
[root@centos6 ~]#curl -v http://10.0.0.7/index.html
[root@centos6 ~]#curl -vA 'firefox' http://192.168.80.110:81/index.html
[root@centos6 ~]#curl -vA 'chrome' http://192.168.80.110:81/index.html


5.rdp-cookie(name)
rdp(windows 远程桌面协议)-cookie 用于对 windows 远程桌面的反向代理,主要是使用 cookie 保持来会话;此调度算法专门适用于 windows 远程桌面连接场景。当连接到后端服务器后,会生成一个cookie,下次相同的cookie连接时,还会被调度到同一台后端服务器,适用于后端多服务器场景。
rdp-cookie一致性hash也可以使用基于iptables实现。  
注:如果跨网段,HAProxy 主机需要开启路由器转发功能/etc/sysctl.conf;,


listen zzhz
    bind 192.168.80.110:81 #IP地址
    mode http
    log global

#   balance source
#   balance uri
#   balance url_param name,age
#   balance hdr(User-Agent) #hdr(host)
    balance rdp-cookie
	
#   hash-type map-based
    hash-type consistent
    server web1 192.168.80.110:80 weight 1 check inter 3000 fall 2 rise 5
    server web2 192.168.80.120:80 weight 3 check inter 3000 fall 3 rise 5

  

  

其它说明

算法总结:
算法		支持的协议		静态/动态
static-rr--------->tcp/http             静态 
first------------->tcp/http             静态 
roundrobin-------->tcp/http             动态 
leastconn--------->tcp/http             动态 
random------------>tcp/http             动态 
source------------>tcp/http             取决于 hash_type 是否 consistent(consistent能调整权重,反之不能)。
Uri--------------->http                 取决于 hash_type 是否 consistent(consistent能调整权重,反之不能)。
url_param--------->http  	        取决于 hash_type 是否 consistent(consistent能调整权重,反之不能)。
hdr--------------->http 	        取决于 hash_type 是否 consistent(consistent能调整权重,反之不能)。
rdp-cookie-------->tcp		        取决于 hash_type 是否 consistent(consistent能调整权重,反之不能)。


各算法使用场景:
算法		使用场景
first		使用较少,节约成本
static-rr	做了 session 共享的 web 集群
roundrobin	做了 session 共享的 web 集群
random		做了 session 共享的 web 集群
leastconn	数据库
source		基于客户端公网 IP 的会话保持
uri		缓存服务器,CDN 服务商,蓝汛、百度、阿里云、腾讯
url		缓存服务器,CDN 服务商,蓝汛、百度、阿里云、腾讯
hdr		基于客户端请求报文头部做下一步处理
rdp-cookie	很少使用