HAProxy 調(diào)度算法介紹
HAProxy 的調(diào)度算法比較多,在沒(méi)有設(shè)置 mode 或者其它選項(xiàng)時(shí),HAProxy 默認(rèn)對(duì)
后端服務(wù)器使用 roundrobin 算法來(lái)分配請(qǐng)求處理。對(duì)后端服務(wù)器指明使用的算法
時(shí)使用balance
關(guān)鍵字,該關(guān)鍵字可在listen
和backend
中出現(xiàn)。在 HAProxy
運(yùn)行時(shí)支持動(dòng)態(tài)調(diào)整后端服務(wù)器權(quán)重、并且考慮后端服務(wù)器負(fù)載等情況的算法,我們
稱(chēng)之為動(dòng)態(tài)算法;相反,不能動(dòng)態(tài)調(diào)整后端服務(wù)器權(quán)重也不考慮服務(wù)器負(fù)載的
算法叫靜態(tài)算法。指定調(diào)度策略的典型配置如下:
backend srv_group1
mode http
log global
# balance <algorithm> [<arguments>]
balance static-rr
server web1 ip:port weight 2 check inter 300000ms fall 2 rise 5
調(diào)度算法官方文檔說(shuō)明
本文介紹 HAProxy 算法的同時(shí),使用一臺(tái) HAProxy 服務(wù)器和四臺(tái)后端服務(wù)器來(lái)驗(yàn)證各
調(diào)度算法的效果。另外,客戶(hù)端使用172.20.2.195 client-node1
,使用該客戶(hù)端訪(fǎng)
問(wèn) HAProxy 服務(wù)器(http://172.20.2.189:8080)來(lái)驗(yàn)證。
-
HAProxy 服務(wù)器
- 172.20.2.189 ubuntu-suosuoli-node1
- 系統(tǒng):Ubuntu1804 四臺(tái)后端服務(wù)器
- 172.20.2.37 node1
- 172.20.2.43 node2
- 172.20.2.44 node3
- 172.20.2.45 node4
- 系統(tǒng)都為 CentOS7.7 客戶(hù)端
- 172.20.2.195 client-node1
- 系統(tǒng)為 CentOS7.7
準(zhǔn)備環(huán)境
root@ubuntu-suosuoli-node1:~# vim /etc/ansible/ansible.cfg
......
[backend]
172.20.2.37
172.20.2.43
172.20.2.44
172.20.2.45
......
root@ubuntu-suosuoli-node1:~# ansible backend -m shell -a "nginx -t"
172.20.2.43 | SUCCESS | rc=0 >>
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
172.20.2.45 | SUCCESS | rc=0 >>
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
172.20.2.37 | SUCCESS | rc=0 >>
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
172.20.2.44 | SUCCESS | rc=0 >>
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@ubuntu-suosuoli-node1:~# ansible backend -m shell -a "nginx -s reload"
172.20.2.37 | SUCCESS | rc=0 >>
172.20.2.45 | SUCCESS | rc=0 >>
172.20.2.43 | SUCCESS | rc=0 >>
172.20.2.44 | SUCCESS | rc=0 >>
root@ubuntu-suosuoli-node1:~# ansible backend -a "hostname"
172.20.2.43 | SUCCESS | rc=0 >>
node2
172.20.2.44 | SUCCESS | rc=0 >>
node3
172.20.2.45 | SUCCESS | rc=0 >>
node4
172.20.2.37 | SUCCESS | rc=0 >>
node1
使用的核心配置
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
nbproc 2
cpu-map 1 0
cpu-map 2 1
stats socket /run/haproxy/admin.sock2 mode 660 level admin expose-fd listeners
#stats socket /run/haproxy/admin.sock1 mode 660 level admin expose-fd listeners process 1
#stats socket /run/haproxy/admin.sock2 mode 660 level admin expose-fd listeners process 2
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
defaults
log global
mode http
option httplog
option dontlognull
option http-keep-alive
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_8080
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
# balance roundrobin 默認(rèn)使用該調(diào)度策略
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
訪(fǎng)問(wèn) WEB 管理界面http://172.20.2.189:9999/haproxy_status
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-QFbYRf6R-1692491218897)(png/2020-01-11-19-40-48.png)]
一.靜態(tài)調(diào)度算法
靜態(tài)算法:按照事先定義好的規(guī)則輪詢(xún)公平調(diào)度,不關(guān)心后端服務(wù)器的當(dāng)前負(fù)載、鏈接數(shù)
和相應(yīng)速度等,且無(wú)法實(shí)時(shí)修改權(quán)重,只能靠重啟 HAProxy 生效。
HAProxy 運(yùn)行時(shí),要?jiǎng)討B(tài)修改服務(wù)器權(quán)重,需要安裝額外的工具socat
。Socat 是 Linux
下的命令行工具,全名叫 Socket CAT
,Socat 的主要工作原理是建立一個(gè)雙向的通道,
并在這個(gè)通道傳輸比特流。其支持眾多協(xié)議和鏈接方式。如 IP、TCP、UDP、IPv6、Socket
文件等。由于其功能強(qiáng)大,可以有多種用途,由于其可以轉(zhuǎn)發(fā) TCP 流,甚至有人將它配置為
防火墻。
# Centos安裝
yum install socat -y
# 此處使用Ubuntu1804
root@ubuntu-suosuoli-node1:~# apt-cache madison socat
socat | 1.7.3.2-2ubuntu2 | http://mirrors.aliyun.com/ubuntu bionic/main amd64 Packages
socat | 1.7.3.2-2ubuntu2 | https://mirrors.tuna.tsinghua.edu.cn/ubuntu bionic/main amd64 Packages
socat | 1.7.3.2-2ubuntu2 | http://mirrors.aliyun.com/ubuntu bionic/main Sources
root@ubuntu-suosuoli-node1:~# apt install socat
root@ubuntu-suosuoli-node1:~# socat -V
socat by Gerhard Rieger and contributors - see www.dest-unreach.org # 這是它官網(wǎng),作者應(yīng)該是個(gè)極簡(jiǎn)主義者
socat version 1.7.3.2 on Apr 4 2018 10:06:49
......
# 獲取后端服務(wù)器node3的權(quán)重可以這樣做
root@ubuntu-suosuoli-node1:~# find / -name admin.sock
/run/haproxy/admin.sock
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node3" | socat stdio /run/haproxy/admin.sock
3 (initial 3)
# 設(shè)置沒(méi)某個(gè)后端服務(wù)器的權(quán)重可以這樣,但是我用的是static-rr算法,不可以動(dòng)態(tài)調(diào)整權(quán)重。只接受0或者1
# 0就表示不參與請(qǐng)求處理,1表示參與
root@ubuntu-suosuoli-node1:~# echo "set weight web_prot_http_nodes/node3 6" | socat stdio /run/haproxy/admin.sock
Backend is using a static LB algorithm and only accepts weights '0%' and '100%'.
BTW:socat 官網(wǎng)
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-Yb4V8Ncy-1692491218898)(png/2020-01-12-14-35-26.png)]
1.1 static-rr
static roundrobin
:靜態(tài)輪詢(xún)調(diào)度策略,使用基于權(quán)重的輪詢(xún)調(diào)度策略。權(quán)重
在配置文件中指定后不可動(dòng)態(tài)更改和后端服務(wù)器慢啟動(dòng),此調(diào)度策略對(duì)后端服務(wù)
器最大數(shù)量沒(méi)有限制。
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance static-rr
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 2 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 2 check inter 3000 fall 3 rise 5
client-node1 上測(cè)試效果
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ; sleep 0.1 ; done
node1 172.20.2.37
node2 172.20.2.43
node4 172.20.2.45
node2 172.20.2.43
node3 172.20.2.44
node4 172.20.2.45
node1 172.20.2.37
node2 172.20.2.43
......
# 44此訪(fǎng)問(wèn),被調(diào)度的比例接近1:2:1:2的權(quán)重值
[root@client-node1 ~]# cat static-rr.log | wc -l
44
[root@client-node1 ~]# cat static-rr.log | sort | uniq -c
8 node1 172.20.2.37
15 node2 172.20.2.43
7 node3 172.20.2.44
14 node4 172.20.2.45
1.2 first
first
:根據(jù)服務(wù)器在列表中的位置,自上而下進(jìn)行調(diào)度(不人為的設(shè)定,從上到
下各臺(tái)服務(wù)器的 id 會(huì)自動(dòng)增加,第一臺(tái)服務(wù)器的 id 為 1),但是其只會(huì)當(dāng)?shù)谝?br> 臺(tái)服務(wù)器的連接數(shù)達(dá)到上限(maxconn
參數(shù)),新請(qǐng)求才會(huì)分配給下一臺(tái)服務(wù),
因此 HAProxy 會(huì)忽略服務(wù)器的權(quán)重值,這樣比較適合長(zhǎng)會(huì)話(huà)的協(xié)議如:RDP[^1]
和 IMAP。不指定maxconn
參數(shù)使用該調(diào)度策略是沒(méi)有意義的(懂我意思嗎?)。
實(shí)現(xiàn)該調(diào)度算法的實(shí)際用途是在比較空閑的時(shí)間段關(guān)閉某些服務(wù)器以使用最少的服
務(wù)器提供服務(wù),節(jié)約成本。
如果需要人為指定 id,則可以在server server_name ip:port
指令后面加上id <idnumber>
id 號(hào)必須是正整數(shù)。
RDP 協(xié)議介紹
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance first
option forwardfor
server node1 172.20.2.37:80 maxconn 2 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 2 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 maxconn 2 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 2 check inter 3000 fall 3 rise 5
client-node1 上測(cè)試
# 在兩個(gè)窗口同時(shí)訪(fǎng)問(wèn)HAProxy
[root@client-node1 ~]# tty
/dev/pts/0
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ; done
...
[root@client-node1 ~]# tty
/dev/pts/1
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ; done
node1 172.20.2.37
node1 172.20.2.37
node2 172.20.2.43
......
node1 172.20.2.37
node1 172.20.2.37
node2 172.20.2.43
......
# 可以看到,在某些時(shí)間幾乎同時(shí)有兩個(gè)以上的請(qǐng)求到達(dá)node1,這時(shí)HAProxy
# 就會(huì)調(diào)度node2處理多出的請(qǐng)求
二.動(dòng)態(tài)調(diào)度算法
2.1 roundrobin
roundrobin
該算法是默認(rèn)使用的調(diào)度策略。該算法會(huì)根據(jù)每個(gè)后端服務(wù)器的
權(quán)重weight
依次將請(qǐng)求分發(fā)到后端服務(wù)器。當(dāng)后端服務(wù)器的處理性能比較均
衡的分布時(shí),使用該算法比較好。在該算法使用時(shí),可以動(dòng)態(tài)調(diào)整后端服務(wù)器
的權(quán)重,以便調(diào)整整個(gè)服務(wù)器組的性能。由于設(shè)計(jì)的限制,每個(gè)后端服務(wù)器組
最多只能定義 4095 個(gè)活動(dòng)服務(wù)器。該 roudrobin 算法支持慢啟動(dòng)(slow
start),表示新加入的服務(wù)器會(huì)在一段時(shí)間內(nèi)逐漸增加工作負(fù)載(轉(zhuǎn)發(fā)量)。
驗(yàn)證 roundrobin 調(diào)度策略的配置如下
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_8080
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
# balance roundrobin 默認(rèn)使用該調(diào)度策略
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
在client-node1
多次訪(fǎng)問(wèn)http://172.20.2.189:8080
驗(yàn)證
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ; sleep 3 ; done
node4 172.20.2.45
node1 172.20.2.37
node2 172.20.2.43
node3 172.20.2.44
node4 172.20.2.45
node1 172.20.2.37
node2 172.20.2.43
^C
# 配置指明后端服務(wù)器的權(quán)重weight都為1,所以后端服務(wù)器被輪流調(diào)度處理請(qǐng)求
更改服務(wù)器的權(quán)重
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node1" | socat stdio /run/haproxy/admin.sock
1 (initial 1)
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node2" | socat stdio /run/haproxy/admin.sock
1 (initial 1)
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node3" | socat stdio /run/haproxy/admin.sock
1 (initial 1)
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node4" | socat stdio /run/haproxy/admin.sock
1 (initial 1)
# 更改權(quán)重
root@ubuntu-suosuoli-node1:~# echo "set weight web_prot_http_nodes/node2 2" | socat stdio /run/haproxy/admin.sock
root@ubuntu-suosuoli-node1:~# echo "set weight web_prot_http_nodes/node3 3" | socat stdio /run/haproxy/admin.sock
root@ubuntu-suosuoli-node1:~# echo "set weight web_prot_http_nodes/node4 4" | socat stdio /run/haproxy/admin.sock
# 查看是否生效
root@ubuntu-suosuoli-node1:~# echo "get weight web_prot_http_nodes/node3" | socat stdio /run/haproxy/admin.sock
3 (initial 1)
再次測(cè)試
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ;sleep 0.01; done
node4 172.20.2.45
node3 172.20.2.44
node4 172.20.2.45
node2 172.20.2.43
node3 172.20.2.44
node4 172.20.2.45
node1 172.20.2.37
node4 172.20.2.45
node3 172.20.2.44
......
# 統(tǒng)計(jì)81次訪(fǎng)問(wèn)
[root@client-node1 ~]# cat statis.log | wc -l
81
[root@client-node1 ~]# cat statis.log | sort | uniq -c
8 node1 172.20.2.37
16 node2 172.20.2.43
24 node3 172.20.2.44
33 node4 172.20.2.45
# 可以看到各個(gè)服務(wù)器被調(diào)度的比例接近權(quán)重node1:node2:node3:node4=1:2:3:4
# 實(shí)際為node1:node2:node3:node4=8:16:24:33
2.2 leastconn
leastconn
加權(quán)的最少連接的動(dòng)態(tài),支持權(quán)重的運(yùn)行時(shí)調(diào)整和慢啟動(dòng),即當(dāng)前后端
服務(wù)器連接最少的優(yōu)先調(diào)度(新客戶(hù)端連接),比較適合長(zhǎng)連接的場(chǎng)景使用,比如
MySQL 等場(chǎng)景。
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance leastconn
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
三.其它算法
這些算法無(wú)法嚴(yán)格的分為動(dòng)態(tài)或者靜態(tài)算法,可以作為靜態(tài)算法也可可以通過(guò)選項(xiàng)調(diào)整
為動(dòng)態(tài)算法。
3.1 source
source
調(diào)度策略為source IP hash
(源地址哈希),基于客戶(hù)端源地址 hash
并將請(qǐng)求轉(zhuǎn)發(fā)到后端服務(wù)器,默認(rèn)為靜態(tài)方式即取模方式,但是可以通過(guò) hash-type
支持的選項(xiàng)更改,后續(xù)同一個(gè)源地址請(qǐng)求將被轉(zhuǎn)發(fā)至同一個(gè)后端 web 服務(wù)器,比較
適用于 session 保持/緩存業(yè)務(wù)等場(chǎng)景。
源 IP 地址被 HASH 并除以正在運(yùn)行的服務(wù)器的總權(quán)重值,取其結(jié)果的摸,得到一
個(gè)索引,以指定哪個(gè)服務(wù)器將接收請(qǐng)求。這確保了只要沒(méi)有服務(wù)器宕機(jī)或恢復(fù),相
同的客戶(hù)端 IP 地址將始終到達(dá)相同的服務(wù)器。如果運(yùn)算結(jié)果由于運(yùn)行的服務(wù)器數(shù)量
的變化而發(fā)生變化,許多客戶(hù)端請(qǐng)求將被定向到其它臺(tái)服務(wù)器。該算法通常用于 TCP
模式,其中不可以插入 cookie 信息。它也可以在 Internet 上使用,為拒絕會(huì)話(huà)
cookie 的客戶(hù)端提供最佳的粘性。默認(rèn)情況下,這個(gè)算法是靜態(tài)的,這意味著動(dòng)態(tài)
地更改服務(wù)器的權(quán)重不會(huì)有任何影響,但是可以使用"hashtype"關(guān)鍵字來(lái)更改。
hash-type <method>
用來(lái)指定 hash 類(lèi)型,類(lèi)型可以是map-based
或者consistent
hash-type map-based # 不指定時(shí),默認(rèn)使用該哈希方法
hash-type consistent
-
使用 map-based 哈希方法時(shí),哈希表(哈希的結(jié)果)是包含所有活動(dòng)服務(wù)器的靜態(tài)
數(shù)組。該哈希方法會(huì)考慮服務(wù)器權(quán)重。但是在服務(wù)器運(yùn)行時(shí)權(quán)重發(fā)生變化會(huì)被忽略。
核心是按照服務(wù)器在數(shù)組中的位置來(lái)選擇調(diào)度的服務(wù)器,所以當(dāng)服務(wù)器有上線(xiàn)或者下
線(xiàn)時(shí),總權(quán)重會(huì)發(fā)生變化,哈希也就變化了,這會(huì)導(dǎo)致大部分的連接將會(huì)重新被調(diào)度
到不同的服務(wù)器。這種調(diào)度算法不支持慢啟動(dòng)也不適合在使用緩存的場(chǎng)景使用。 -
使用 consistent 一致性哈希方法時(shí),哈希表中每個(gè)服務(wù)器對(duì)應(yīng)多個(gè)哈希值(這些
對(duì)應(yīng)于同一個(gè)服務(wù)器的哈希值和該服務(wù)器的名稱(chēng)或者 ID 有關(guān)聯(lián)),這個(gè)哈希表使用
樹(shù)結(jié)構(gòu)(某種數(shù)據(jù)結(jié)構(gòu))來(lái)組織。HAProxy 會(huì)在該樹(shù)結(jié)構(gòu)上查找哈希鍵,并選中最合適
的值。該哈希方法支持動(dòng)態(tài)修改服務(wù)器權(quán)重,所以其支持慢啟動(dòng)。使用該調(diào)度策略的
優(yōu)勢(shì)是,當(dāng)某個(gè)服務(wù)器停用或者再次啟用時(shí),只有和該服務(wù)器相關(guān)的哈希信息會(huì)被移
除。當(dāng)某個(gè)服務(wù)器加入服務(wù)器組時(shí),只有一部分連接會(huì)被重新分配,這使得一致性哈
希方法是使用緩存時(shí)的理想調(diào)度策略。
map-based
哈希方法
consistent
一致性哈希方法
map-based
哈希方法配置
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance source
# hash-type map-based # 可寫(xiě)可不寫(xiě)
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
在 client-node1 訪(fǎng)問(wèn)驗(yàn)證
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ;sleep 1; done
node4 172.20.2.45
node4 172.20.2.45
node4 172.20.2.45
......
在 172.20.1.1 訪(fǎng)問(wèn)驗(yàn)證
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-SlWTvcYj-1692491218898)(png/2020-01-12-18-00-29.png)]
consistent
一致性哈希方法配置
listen stats
mode tcp
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode tcp
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance source
hash-type consistence # 使用一致性哈希方法
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5`
3.2 uri
uri
調(diào)度算法會(huì)對(duì) URI 的左側(cè)部分(問(wèn)號(hào)前面的部分)或者對(duì)整個(gè) URI 進(jìn)行哈希,
并使用活動(dòng)服務(wù)器的總權(quán)重值除以該哈希值。計(jì)算結(jié)果決定了將請(qǐng)求調(diào)度到哪臺(tái)服
務(wù)器。該調(diào)度算法常常在使用代理緩存時(shí)使用。也可以通過(guò) map-based 和
consistent 定義使用取模法還是一致性 hash。
http://example.org/absolute/URI/with/absolute/path/to/resource.txt #URI/URL
ftp://example.org/resource.txt #URI/URL
/relative/URI/with/absolute/path/to/resource.txt #URI
# 注意:URL是URI的子集
配置示例
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance uri
#hash-type map-based
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
訪(fǎng)問(wèn)測(cè)試
[root@client-node1 ~]# curl http://172.20.2.189:8080/index.html
node3 172.20.2.44
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html
index1-node4-172.20.2.45
3.3 url_param
url_param 對(duì)用戶(hù)請(qǐng)求的 url 中的 params 部分中的參數(shù) name 作 hash
計(jì)算,并除以服務(wù)器總權(quán)重,根據(jù)計(jì)算結(jié)果派發(fā)至某挑出的服務(wù)器;通常用
于追蹤用戶(hù),以確保來(lái)自同一個(gè)用戶(hù)的請(qǐng)求始終發(fā)往同一個(gè) real server。
其亦可以使用hash-type
指定一致性哈希方法。另外,如果找不到 URL 中
問(wèn)號(hào)選項(xiàng)后的參數(shù),則使用 roundrobin 算法。
對(duì)于 url_param 中的哈希對(duì)象(參數(shù)),可以用一個(gè) URL 來(lái)說(shuō)明:
假設(shè)
URL = http://www.suosuoli.cn/foo/bar/index.php?key1=value1&key2=value2
那么
host = "www.suosuoli.cn"
url_param = "key1=value1&key2=value2" # 該字符串就是要進(jìn)行哈希運(yùn)算的對(duì)象
url_param
調(diào)度策略配置示例
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance url_param name,gender # 支持對(duì)單個(gè)或多個(gè)url_param進(jìn)行hash
# hash-type consistent # 使用一致性hash方法
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
訪(fǎng)問(wèn)測(cè)試
# 未帶參數(shù),都被調(diào)度到node1
[root@client-node1 ~]# curl http://172.20.2.189:8080/index.html
node1 172.20.2.37
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html
index1-node2-172.20.2.43
# 找不到參數(shù)則使用roudrobin輪詢(xún)策略
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node3-172.20.2.44
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node4-172.20.2.45
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node1--172.20.2.37
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node2-172.20.2.43
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node3-172.20.2.44
[root@client-node1 ~]# curl http://172.20.2.189:8080/index1.html?name=jack
index1-node4-172.20.2.45
3.4 hdr
針對(duì)用戶(hù)每個(gè) http 頭部(header)請(qǐng)求中的指定信息做 hash,此處由 name 指定
的 http 首部將會(huì)被取出并做 hash 計(jì)算,然后由服務(wù)器總權(quán)重相除以后派發(fā)至某
挑出的服務(wù)器,假如無(wú)有效的值,則會(huì)使用默認(rèn)的輪詢(xún)調(diào)度。
hdr
調(diào)度策略配置
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance hdr(User-Agent) # 使用客服端版本等信息進(jìn)行哈希運(yùn)算
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
訪(fǎng)問(wèn)測(cè)試
[root@client-node1 ~]# curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.36 zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
[root@client-node1 ~]# curl http://172.20.2.189:8080
node4 172.20.2.45
[root@client-node1 ~]# curl http://172.20.2.189:8080
node4 172.20.2.45
[root@client-node1 ~]# curl http://172.20.2.189:8080
node4 172.20.2.45
[root@client-node1 ~]# curl http://172.20.2.189:8080
Chrome 瀏覽器測(cè)試
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-VllpvcMV-1692491218899)(png/2020-01-12-21-05-14.png)]
FireFox 瀏覽器測(cè)試
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來(lái)直接上傳(img-919Z4GWd-1692491218899)(png/2020-01-12-21-06-52.png)]
可以看到不同的客戶(hù)端的請(qǐng)求被調(diào)度到不同的后端服務(wù)器。
3.5 rdp-cookie
rdp(windows 遠(yuǎn)程桌面協(xié)議)-cookie 用于對(duì) windows 遠(yuǎn)程桌面的反向代理,
主要是使用 cookie 保持來(lái)會(huì)話(huà);此調(diào)度算法專(zhuān)門(mén)適用于 windows 遠(yuǎn)程桌面
連接場(chǎng)景。當(dāng)連接到后端服務(wù)器后,會(huì)生成一個(gè) cookie,下次相同的 cookie
連接時(shí),還會(huì)被調(diào)度到同一臺(tái)后端服務(wù)器,適用于后端多服務(wù)器場(chǎng)景。
rdp-cookie
配置示例
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode tcp
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode tcp
balance rdp-cookie
hash-type consistence
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
注:如果跨網(wǎng)段,HAProxy 主機(jī)需要開(kāi)啟路由器轉(zhuǎn)發(fā)功能/etc/sysctl.conf;
net.ipv4.ip_forward = 1 #必須開(kāi)啟ip轉(zhuǎn)發(fā)功能
該算法只在四層,是不分析到用戶(hù)請(qǐng)求的應(yīng)用層信息的,只分析到傳輸層,所以
HAProxy 會(huì)基于端口號(hào)做轉(zhuǎn)發(fā),所以需要開(kāi)啟路由器轉(zhuǎn)發(fā)功能。
3.6 random
該算法在 1.9 版本增加,其基于一個(gè)隨機(jī)數(shù)作為一致性 hash 的 key,隨機(jī)負(fù)載
平衡對(duì)于大型服務(wù)器場(chǎng)或經(jīng)常添加和刪除服務(wù)器的場(chǎng)景非常有用,因?yàn)樗梢员苊?br> 在這種情況下由 roundrobin 或 leastconn 導(dǎo)致的錘擊效應(yīng)。
random
調(diào)度策略配置
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode http
balance random
option forwardfor
server node1 172.20.2.37:80 weight 1 check inter 3000 fall 3 rise 5
server node2 172.20.2.43:80 weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 weight 1 check inter 3000 fall 3 rise 5
訪(fǎng)問(wèn)測(cè)試
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 ;sleep 1; done
node2 172.20.2.43
node1 172.20.2.37
node4 172.20.2.45
node1 172.20.2.37
node1 172.20.2.37
node4 172.20.2.45
node2 172.20.2.43
node4 172.20.2.45
^C
[root@client-node1 ~]# while : ; do curl 172.20.2.189:8080 >> random.log ; done
.....
[root@client-node1 ~]# cat random.log | wc -l
1147
[root@client-node1 ~]# cat random.log | sort | uniq -c
346 node1 172.20.2.37
201 node2 172.20.2.43
266 node3 172.20.2.44
333 node4 172.20.2.45
# 可以看到各個(gè)服務(wù)器處理的請(qǐng)求數(shù)量沒(méi)有規(guī)律,隨機(jī)的(懂我意思嗎?)
四.各算法使用場(chǎng)景
4.1 總結(jié)
算法 | 支持的協(xié)議 | 靜態(tài)/動(dòng)態(tài) |
---|---|---|
static-rr | tcp/http | 靜態(tài) |
first | tcp/http | 靜態(tài) |
roundrobin | tcp/http | 動(dòng)態(tài) |
leastconn | tcp/http | 動(dòng)態(tài) |
random | tcp/http | 動(dòng)態(tài) |
source | tcp/http | 取決于 hash_type 是否 consistent |
uri | ttp | 取決于 hash_type 是否 consistent |
url_param | ttp | 取決于 hash_type 是否 consistent |
hdr | http | 取決于 hash_type 是否 consistent |
rdp-cookie | tcp | 取決于 hash_type 是否 consistent |
4.2 各算法使用場(chǎng)景
算法 | 使用場(chǎng)景 |
---|---|
first | 使用較少,節(jié)約成本 |
static-rr | 做了 session 共享的 web 集群 |
roundrobin | 做了 session 共享的 web 集群 |
random | 做了 session 共享的 web 集群 |
leastconn | 數(shù)據(jù)庫(kù) |
source | 基于客戶(hù)端公網(wǎng) IP 的會(huì)話(huà)保持 |
uri--------------->http | 緩存服務(wù)器,CDN 服務(wù)商,藍(lán)汛、百度、阿里云、騰訊 |
url_param--------->http | 緩存服務(wù)器,CDN 服務(wù)商,藍(lán)汛、百度、阿里云、騰訊 |
hdr | 基于客戶(hù)端請(qǐng)求報(bào)文頭部做下一步處理 |
rdp-cookie | 很少使用 |
五.四層與七層負(fù)載
在 HAProxy 或者 Nginx 等軟件涉及到代理和負(fù)載均衡等概念時(shí)常常會(huì)引出四層和
七層負(fù)載、四層和七層流量等概念。實(shí)際上這里的四層和七層就對(duì)于網(wǎng)絡(luò)協(xié)議棧中
ISO 標(biāo)準(zhǔn)的四層和七層。
層級(jí) | 協(xié)議 |
---|---|
七 | 應(yīng)用層 HTTP/HTTPS/FTP.所以七層代理或者七層負(fù)載主要負(fù)載處理 HTTP 協(xié)議 |
六 | 表示層 |
五 | 會(huì)話(huà)層 |
四 | 傳輸層 TCP/UDP.所以四層轉(zhuǎn)發(fā)或者四層負(fù)載主要處理 TCP 或 UDP 協(xié)議 |
三 | 網(wǎng)絡(luò)層 IP |
二 | 數(shù)據(jù)鏈路層 ARP/RARP |
一 | 物理層 |
處理七層負(fù)載時(shí)主要涉及 HTTP 協(xié)議的請(qǐng)求頭,請(qǐng)求體和請(qǐng)求方法等概念。
處理四層負(fù)載主要是 TCP 協(xié)議,涉及 IP 地址和端口等概念。
5.1 四層負(fù)載
在四層負(fù)載設(shè)備中,把 client 發(fā)送的報(bào)文目標(biāo)地址(原來(lái)是負(fù)載均衡設(shè)備的 IP
地址),根據(jù)均衡設(shè)備設(shè)置的選擇 web 服務(wù)器的規(guī)則選擇對(duì)應(yīng)的 web 服務(wù)器 IP
地址,這樣 client 就可以直接跟此服務(wù)器建立 TCP 連接并發(fā)送數(shù)據(jù)。
5.2 七層負(fù)載
七層負(fù)載均衡服務(wù)器起了一個(gè)反向代理服務(wù)器的作用,服務(wù)器建立一次 TCP 連接
要三次握手,而 client 要訪(fǎng)問(wèn) webserver 要先與七層負(fù)載設(shè)備進(jìn)行三次握手
后建立 TCP 連接,把要訪(fǎng)問(wèn)的報(bào)文信息發(fā)送給七層負(fù)載均衡;然后七層負(fù)載均衡
再根據(jù)設(shè)置的均衡規(guī)則選擇特定的 webserver,然后通過(guò)三次握手與此臺(tái)
webserver 建立 TCP 連接,然后 webserver 把需要的數(shù)據(jù)發(fā)送給七層負(fù)載均衡
設(shè)備,負(fù)載均衡設(shè)備再把數(shù)據(jù)發(fā)送給 client;所以,七層負(fù)載均衡設(shè)備起到了代
理服務(wù)器的作用。
六.IP 透?jìng)?/h2>
IP 透?jìng)鲗?shí)際上就是指將客戶(hù)端的 IP 發(fā)送給后端服務(wù)器,默認(rèn)后端服務(wù)器是不知道
請(qǐng)求來(lái)自哪個(gè)客戶(hù)端的。HAProxy 可以在四層或者七層將客戶(hù)端的 IP 傳給后端
服務(wù)器,以便做訪(fǎng)問(wèn)和日志分析。
6.1 四層 IP 透?jìng)髋渲?/h3>
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode tcp
balance random
option forwardfor
server node1 172.20.2.37:80 send-proxy weight 1 check inter 3000 fall 3 rise 5 # 加send-proxy就可以
server node2 172.20.2.43:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
# 后端Nginx配置:
http {
......
log_format main '"$http_x_forwarded_For" - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
server {
listen 80 proxy_protocol; # 增加選項(xiàng)proxy_protocol
#listen 80;
server_name localhost;
......
access_log logs/host.access.log main;
}
}
6.2 七層 IP 透?jìng)髋渲?/h3>
listen stats
mode http
bind 172.20.2.189:9999
stats enable
log global
stats uri /haproxy_status
stats auth haadmin:stevenux
frontend WEB_PORT_80
bind 172.20.2.189:8080
mode http
use_backend web_prot_http_nodes
backend web_prot_http_nodes
mode tcp
balance random
option forwardfor
server node1 172.20.2.37:80 send-proxy weight 1 check inter 3000 fall 3 rise 5 # 加send-proxy就可以
server node2 172.20.2.43:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
server node3 172.20.2.44:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
server node4 172.20.2.45:80 send-proxy weight 1 check inter 3000 fall 3 rise 5
# 后端Nginx配置:
http {
......
log_format main '"$http_x_forwarded_For" - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" ';
server {
listen 80 proxy_protocol; # 增加選項(xiàng)proxy_protocol
#listen 80;
server_name localhost;
......
access_log logs/host.access.log main;
}
}
當(dāng) haproxy 工作在七層的時(shí)候,如何透?jìng)骺蛻?hù)端真實(shí) IP 至后端服務(wù)器?
6.2.1 HAProxy 配置
# haproxy 配置:
defaults
option forwardfor
# 或者:
option forwardfor header X-Forwarded-xxx # 自定義傳遞IP參數(shù),后端web服務(wù)器寫(xiě)X-Forwarded-xxx,
# 如果寫(xiě)
option forwardfor # 則后端服務(wù)器web格式為X-Forwarded-For
listen配置示例:
listen web_host
bind 192.168.7.101:80
mode http
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
6.2.2 web 服務(wù)器日志格式配置
配置 web 服務(wù)器,以記錄負(fù)載均衡透?jìng)鞯目蛻?hù)端 IP 地址文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-669541.html
# 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" ';
訪(fǎng)問(wèn)測(cè)試文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-669541.html
# 172.20.1.1為客戶(hù)端地址
[root@node1 ~]# tail -f /apps/nginx/logs/access.log
"172.20.2.195" - - [13/Jan/2020:19:01:38 +0800] "GET / HTTP/1.1" 200 18 "-" "curl/7.29.0"
"172.20.1.1" - - [13/Jan/2020:19:01:49 +0800] "GET /index1.html HTTP/1.1" 200 26 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"
"172.20.1.1" - - [13/Jan/2020:19:01:52 +0800] "GET /index1.html HTTP/1.1" 200 26 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"
"172.20.1.1" - - [13/Jan/2020:19:01:55 +0800] "GET /index1.html HTTP/1.1" 200 26 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"
"172.20.1.1" - - [13/Jan/2020:19:02:22 +0800] "GET /index1.html HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"
......
到了這里,關(guān)于HAProxy 調(diào)度算法介紹的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!