1吱抚、簡述keepalived工作原理
Keepalived軟件起初是專為LVS負(fù)載均衡軟件設(shè)計的,用來管理并監(jiān)控LVS集群系統(tǒng)中各個服務(wù)節(jié)點的狀態(tài),后來又加入了可以實現(xiàn)高可用的VRRP功能昙篙。因此腊状,Keepalived除了能夠管理LVS軟件外,還可以作為其他服務(wù)(例如:Nginx苔可、Haproxy缴挖、MySQL等)的高可用解決方案軟件。
Keepalived采用是模塊化設(shè)計焚辅,不同模塊實現(xiàn)不同的功能映屋。
keepalived主要有三個模塊,分別是core同蜻、check和vrrp棚点。
core:是keepalived的核心,負(fù)責(zé)主進(jìn)程的啟動和維護(hù)湾蔓,全局配置文件的加載解析等
check: 負(fù)責(zé)healthchecker(健康檢查)瘫析,包括了各種健康檢查方式,以及對應(yīng)的配置的解析包括LVS的配置解析默责;可基于腳本檢查對IPVS后端服務(wù)器健康狀況進(jìn)行檢查
vrrp:VRRPD子進(jìn)程贬循,VRRPD子進(jìn)程就是來實現(xiàn)VRRP協(xié)議的
Keepalived配置文件:keepalived.conf
主要有三個配置區(qū)域,分別是:全局配置(Global Configuration)桃序、VRRPD配置杖虾、LVS配置
全局配置又包括兩個子配置: 全局定義(global definition) 靜態(tài)IP地址/路由配置(static
ipaddress/routes)
Keepalived服務(wù)VRRP的工作原理:
Keepalived高可用對之間是通過 VRRP進(jìn)行通信的, VRRP是通過競選機(jī)制來確定主備的媒熊,主的優(yōu)先級高于備奇适,因此,工作時主會優(yōu)先獲得所有的資源芦鳍,備節(jié)點處于等待狀態(tài)嚷往,當(dāng)主宕機(jī)的時候,備節(jié)點就會接管主節(jié)點的資源怜校,然后頂替主節(jié)點對外提供服務(wù)
在Keepalived服務(wù)對之間间影,只有作為主的服務(wù)器會一直發(fā)送 VRRP廣播包,告訴備它還活著注竿,此時備不會搶占主茄茁,當(dāng)主不可用時,即備監(jiān)聽不到主發(fā)送的廣播包時巩割,就會啟動相關(guān)服務(wù)接管資源裙顽,保證業(yè)務(wù)的連續(xù)性.接管速度最快
出現(xiàn)腦裂的原因:
高可用服務(wù)器對之間心跳線鏈路發(fā)生故障,導(dǎo)致無法正常通信宣谈。
因心跳線壞了(包括斷了愈犹,老化)。
因網(wǎng)卡及相關(guān)驅(qū)動壞了,ip配置及沖突問題(網(wǎng)卡直連)
因心跳線間連接的設(shè)備故障(網(wǎng)卡及交換機(jī))
因仲裁的機(jī)器出問題(采用仲裁的方案)
高可用服務(wù)器上開啟了 iptables防火墻阻擋了心跳消息傳輸漩怎。
高可用服務(wù)器上心跳網(wǎng)卡地址等信息配置不正確勋颖,導(dǎo)致發(fā)送心跳失敗
其他服務(wù)配置不當(dāng)?shù)仍颍缧奶绞讲煌福奶鴱V插沖突饭玲、軟件Bug等。
如何解決腦裂:
① 同時使用串行電纜和以太網(wǎng)電纜連接叁执,同時用兩條心跳線路茄厘,這樣一條線路壞了,另一個還是好的谈宛,依然能傳送心跳消息次哈。
② 當(dāng)檢測到裂腦時強(qiáng)行關(guān)閉一個心跳節(jié)點(這個功能需特殊設(shè)備支持,如Stonith吆录、feyce)窑滞。相當(dāng)于備節(jié)點接收不到心跳消患,通過單獨的線路發(fā)送關(guān)機(jī)命令關(guān)閉主節(jié)點的電源径筏。
③ 做好對裂腦的監(jiān)控報警(如郵件及手機(jī)短信等或值班).在問題發(fā)生時人為第一時間介入仲裁葛假,降低損失。管理員可以通過手機(jī)回復(fù)對應(yīng)數(shù)字或簡單的字符串操作返回給服務(wù)器.讓服務(wù)器根據(jù)指令自動處理相應(yīng)故障這樣解決故障的時間更短滋恬。
2聊训、編譯安裝haproxy
編譯安裝HAProxy 2.0 LTS版本,更多源碼包下載地址:http://www.haproxy.org/download/
1 解決 lua 環(huán)境
HAProxy 支持基于lua實現(xiàn)功能擴(kuò)展恢氯,lua是一種小巧的腳本語言带斑,于1993年由巴西里約熱內(nèi)盧天主教大學(xué)(Pontifical Catholic University of Rio de Janeiro)里的一個研究小組開發(fā),其設(shè)計目的是為了嵌入應(yīng)用程序中勋拟,從而為應(yīng)用程序提供靈活的擴(kuò)展和定制功能勋磕。
Lua 官網(wǎng):www.lua.org
Lua 應(yīng)用場景
? 游戲開發(fā)
? 獨立應(yīng)用腳本
? Web 應(yīng)用腳本
? 擴(kuò)展和數(shù)據(jù)庫插件,如MySQL Proxy
? 安全系統(tǒng)敢靡,如入侵檢測系統(tǒng)
1.1 CentOS 基礎(chǔ)環(huán)境
由于CentOS7 之前版本自帶的lua版本比較低并不符合HAProxy要求的lua最低版本(5.3)的要求挂滓,因此需要編譯安裝較新版本的lua環(huán)境,然后才能編譯安裝HAProxy啸胧,過程如下:
#當(dāng)前系統(tǒng)版本
[root@centos7 ~]#lua -v
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
#安裝基礎(chǔ)命令及編譯依賴環(huán)境
[root@centos7 ~]# yum install gcc readline-devel
[root@centos7 ~]# curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
[root@centos7 ~]# tar zxf lua-5.3.5.tar.gz
[root@centos7 ~]# cd lua-5.3.5
[root@centos7 lua-5.3.5]# make all test
#查看編譯安裝的版本
[root@centos7 lua-5.3.5]#mkdir /usr/local/lua
[root@centos7 lua-5.3.5]#mv src/ /usr/local/lua/
[root@centos7 lua-5.3.5]#src/lua -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
1.2 Ubuntu 基礎(chǔ)環(huán)境
#安裝基礎(chǔ)命令及編譯依賴環(huán)境
# apt install gcc iproute2 ntpdate tcpdump telnet traceroute nfs-kernel-server
nfs-common lrzsz tree openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev
openssh-server libreadline-dev libsystemd-dev
# cd /usr/local/src
# wget http://www.lua.org/ftp/lua-5.3.5.tar.gz
# tar xvf lua-5.3.5.tar.gz
# cd lua-5.3.5
# make linux test
# pwd
/usr/local/src/lua-5.3.5
# ./src/lua -v
Lua 5.3.3 Copyright (C) 1994-2018 Lua.org, PUC-Rio
#或安裝系統(tǒng)自帶的lua
# apt install lua5.3=5.3.3-1ubuntu0.18.04.1
# lua5.3 -v
Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio
2 編譯安裝HAProxy
#HAProxy 1.8及1.9版本編譯參數(shù):
make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
#HAProxy 2.0以上版本編譯參數(shù):
[root@centos7 ~]#yum -y install gcc openssl-devel pcre-devel systemd-devel
[root@centos7 ~]#tar xvf haproxy-2.4.1.tar.gz -C /usr/local/src
[root@centos7 ~]#cd /usr/local/src/haproxy-2.4.1/
#參考INSTALL文件進(jìn)行編譯安裝
[root@centos7 haproxy-2.4.1]#make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_LUA=1 LUA_INC=/usr/local/lua/src/ LUA_LIB=/usr/local/lua/src/
[root@centos7 haproxy-2.4.1]# make install PREFIX=/apps/haproxy
[root@centos7 haproxy-2.4.1]# ln -s /apps/haproxy/sbin/haproxy /usr/sbin/
3 驗證HAProxy版本
[root@centos7 ~]#haproxy -v
HA-Proxy version 2.4.1 2022/04/17 - https://haproxy.org/
#大寫-V選項顯示版本和幫助用法
[root@centos7 ~]#haproxy -V
4 準(zhǔn)備HAProxy啟動文件
#默認(rèn)缺少配置文件赶站,無法啟動
[root@centos7 ~]#systemctl daemon-reload
[root@centos7 ~]#systemctl start haproxy
#創(chuàng)建service文件
[root@centos7 ~]#vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p
/var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
5 配置文件
#創(chuàng)建自定義的配置文件
[root@centos7 ~]# mkdir /etc/haproxy
[root@centos7 ~]# vim /etc/haproxy/haproxy.cfg
global
maxconn 100000
chroot /apps/haproxy
stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
#uid 99
#gid 99
user haproxy
group haproxy
daemon
#nbproc 4
#cpu-map 1 0
#cpu-map 2 1
#cpu-map 3 2
#cpu-map 4 3
pidfile /var/lib/haproxy/haproxy.pid
log 127.0.0.1 local2 info
defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms
listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:123456
listen web_port
bind 10.0.0.7:80
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5
6 啟動 haproxy
#準(zhǔn)備socket文件目錄
[root@centos7 ~]# mkdir /var/lib/haproxy
#設(shè)置用戶和目錄權(quán)限
[root@centos7 ~]# useradd -r -s /sbin/nologin -d /var/lib/haproxy haproxy
[root@centos7 ~]# systemctl enable --now haproxy
7 驗證 haproxy 狀態(tài)
haproxy.cfg文件中定義了chroot、pidfile贝椿、user烙博、group等參數(shù)渣窜,如果系統(tǒng)沒有相應(yīng)的資源會導(dǎo)致haproxy無法啟動夷都,具體參考日志文件 /var/log/messages
[root@centos7 ~]# systemctl status haproxy
8 查看haproxy的狀態(tài)頁面
瀏覽器訪問: http://10.0.0.17:9999/haproxy-status
3予颤、總結(jié)haproxy各調(diào)度算法的實現(xiàn)方式及其應(yīng)用場景
HAProxy通過固定參數(shù) balance 指明對后端服務(wù)器的調(diào)度算法,該參數(shù)可以配置在listen或backend選項中 。
HAProxy的調(diào)度算法分為靜態(tài)和動態(tài)調(diào)度算法刑顺,但是有些算法可以根據(jù)參數(shù)在靜態(tài)和動態(tài)算法中相互轉(zhuǎn)換。
1 靜態(tài)算法
靜態(tài)算法:按照事先定義好的規(guī)則輪詢進(jìn)行調(diào)度贝淤,不關(guān)心后端服務(wù)器的當(dāng)前負(fù)載播聪、連接數(shù)和響應(yīng)速度等离陶,且無法實時動態(tài)修改權(quán)重(只能為0和1招刨,不支持其它值)或者修改后不生效,如果需要修改只能靠重啟HAProxy生效。
1.1 socat 工具
對服務(wù)器動態(tài)權(quán)重和其它狀態(tài)可以利用 socat工具進(jìn)行調(diào)整学密,Socat 是 Linux 下的一個多功能的網(wǎng)絡(luò)工具,名字來由是Socket CAT,相當(dāng)于netCAT的增強(qiáng)版.Socat 的主要特點就是在兩個數(shù)據(jù)流之間建立雙向通道试幽,且支持眾多協(xié)議和鏈接方式。如 IP济榨、TCP擒滑、 UDP、IPv6丐一、Socket文件等
[root@proxy ~]#yum -y install socat
[root@proxy ~]#vim /etc/haproxy/haproxy.cfg #主配置設(shè)置兩個進(jìn)程
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
[root@proxy ~]#echo "get weight m44_webservers1/rs1" | socat stdio /var/lib/haproxy/haproxy.sock1
1 (initial 1)
[root@proxy ~]#echo "get weight m44_webservers1/rs1" | socat stdio /var/lib/haproxy/haproxy.sock2
1 (initial 1)
[root@proxy ~]#echo "set weight m44_webservers1/rs1 0" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "set weight m44_webservers1/rs1 0" | socat stdio /var/lib/haproxy/haproxy.sock2
#測試
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@proxy ~]#echo "disable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "disable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock2
#測試
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@centos7 ~]#curl 10.0.0.7
SorryServer
[root@proxy ~]#echo "enable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "enable server m44_webservers1/rs2" | socat stdio /var/lib/haproxy/haproxy.sock2
#測試
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@proxy ~]#echo "set weight m44_webservers1/rs1 3" | socat stdio /var/lib/haproxy/haproxy.sock1
[root@proxy ~]#echo "set weight m44_webservers1/rs1 3" | socat stdio /var/lib/haproxy/haproxy.sock2
#測試
[root@centos7 ~]#curl 10.0.0.7
10.0.0.28
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
[root@centos7 ~]#curl 10.0.0.7
10.0.0.18
1.2 static-rr
static-rr:基于權(quán)重的輪詢調(diào)度淹冰,該算法與輪循算法相似,只是它是靜態(tài)的樱拴,這意味著動態(tài)更改服務(wù)器的權(quán)重不會產(chǎn)生任何影響凝颇。不支持運行時利用socat進(jìn)行權(quán)重的動態(tài)調(diào)整(只支持0和1疹鳄,不支持其它值)及后端服務(wù)器慢啟動瘪弓,其后端主機(jī)數(shù)量沒有限制袱饭,相當(dāng)于LVS中的 wrr
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance static-rr
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
1.3 first
first:根據(jù)服務(wù)器在列表中的位置虑乖,自上而下進(jìn)行調(diào)度疹味,但是其只會當(dāng)?shù)谝慌_服務(wù)器的連接數(shù)達(dá)到上限仅叫,新請求才會分配給下一臺服務(wù),因此會忽略服務(wù)器的權(quán)重設(shè)置糙捺,此方式使用較少
不支持用socat進(jìn)行動態(tài)修改權(quán)重,可以設(shè)置0和1,可以設(shè)置其它值但無效
#代碼實現(xiàn)
maxconn <maxconn> #當(dāng)前后端server的最大并發(fā)連接數(shù)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance first
server rs1 10.0.0.18:80 maxconn 1 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試诫咱,同時運行下面命令,觀察結(jié)果
[root@client ~]#while true :;do curl http://10.0.0.7/index.html;sleep 0.1;done
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
2 動態(tài)算法
動態(tài)算法:基于后端服務(wù)器狀態(tài)進(jìn)行調(diào)度適當(dāng)調(diào)整洪灯,新請求將優(yōu)先調(diào)度至當(dāng)前負(fù)載較低的服務(wù)器坎缭,且權(quán)重可以在haproxy運行時動態(tài)調(diào)整無需重啟。
2.1 roundrobin
roundrobin:基于權(quán)重的輪詢動態(tài)調(diào)度算法签钩,支持權(quán)重的運行時調(diào)整掏呼,不同于lvs中的rr輪訓(xùn)模式,HAProxy中的roundrobin支持慢啟動(新加的服務(wù)器會逐漸增加轉(zhuǎn)發(fā)數(shù))铅檩,其每個后端backend中最多支持4095個real server哄尔,支持對real server權(quán)重動態(tài)調(diào)整,roundrobin為默認(rèn)調(diào)度算法柠并,此算法使用廣泛
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance roundrobin
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 2 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
2.2 leastconn
leastconn 加權(quán)的最少連接的動態(tài)岭接,支持權(quán)重的運行時調(diào)整和慢啟動,即:根據(jù)當(dāng)前連接最少的后端服務(wù)器而非權(quán)重進(jìn)行優(yōu)先調(diào)度(新客戶端連接)臼予,比較適合長連接的場景使用鸣戴,比如:MySQL等場景。
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance leastconn
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
2.3 random
在1.9版本開始增加 random的負(fù)載平衡算法粘拾,其基于隨機(jī)數(shù)作為一致性hash的key窄锅,隨機(jī)負(fù)載平衡對于大型服務(wù)器場或經(jīng)常添加或刪除服務(wù)器非常有用,支持weight的動態(tài)調(diào)整缰雇,weight較大的主機(jī)有更大概率獲取新請求
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance random
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.28
[root@client ~]#curl 10.0.0.7
10.0.0.18
3 其他算法
其它算法即可作為靜態(tài)算法入偷,又可以通過選項成為動態(tài)算法
3.1 source
源地址hash,基于用戶源地址hash并將請求轉(zhuǎn)發(fā)到后端服務(wù)器械哟,后續(xù)同一個源地址請求將被轉(zhuǎn)發(fā)至同一個后端web服務(wù)器疏之。此方式當(dāng)后端服務(wù)器數(shù)據(jù)量發(fā)生變化時,會導(dǎo)致很多用戶的請求轉(zhuǎn)發(fā)至新的后端服務(wù)器暇咆,默認(rèn)為靜態(tài)方式锋爪,但是可以通過hash-type選項進(jìn)行更改
這個算法一般是在不插入Cookie的TCP模式下使用,也可給不支持會話cookie的客戶提供最好的會話粘性爸业,適用于session會話保持但不支持cookie和緩存的場景
源地址有兩種轉(zhuǎn)發(fā)客戶端請求到后端服務(wù)器的服務(wù)器選取計算方式其骄,分別是取模法和一致性hash
3.1.1 map-base 取模法
map-based:取模法,對source地址進(jìn)行hash計算扯旷,再基于服務(wù)器總權(quán)重的取模拯爽,最終結(jié)果決定將此請求轉(zhuǎn)發(fā)至對應(yīng)的后端服務(wù)器。此方法是靜態(tài)的钧忽,即不支持在線調(diào)整權(quán)重毯炮,不支持慢啟動逼肯,可實現(xiàn)對后端服務(wù)器均衡調(diào)度。缺點是當(dāng)服務(wù)器的總權(quán)重發(fā)生變化時否副,即有服務(wù)器上線或下線,都會因總權(quán)重發(fā)生變化而導(dǎo)致調(diào)度結(jié)果整體改變崎坊,hash-type 指定的默認(rèn)值為此算法
所謂取模運算备禀,就是計算兩個數(shù)相除之后的余數(shù),10%7=3, 7%4=3
map-based算法:基于權(quán)重取模奈揍,hash(source_ip)%所有后端服務(wù)器相加的總權(quán)重
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance source
hash-type map-base
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
3.1.2 一致性 hash
一致性哈希曲尸,當(dāng)服務(wù)器的總權(quán)重發(fā)生變化時,對調(diào)度結(jié)果影響是局部的男翰,不會引起大的變動另患,
hash(o)mod n ,該hash算法是動態(tài)的蛾绎,支持使用 socat等工具進(jìn)行在線權(quán)重調(diào)整昆箕,支持慢啟動
算法:
1、key1=hash(source_ip)%(2^32) [0---4294967295]
2租冠、keyA=hash(后端服務(wù)器虛擬ip)%(2^32)
3鹏倘、將key1和keyA都放在hash環(huán)上,將用戶請求調(diào)度到離key1最近的keyA對應(yīng)的后端服務(wù)器
hash環(huán)偏斜問題
增加虛擬服務(wù)器IP數(shù)量顽爹,比如:一個后端服務(wù)器根據(jù)權(quán)重為1生成1000個虛擬IP纤泵,再hash。而后端服務(wù)器權(quán)重為2則生成2000的虛擬IP镜粤,再進(jìn)行hash運算,最終在hash環(huán)上生成3000個節(jié)點捏题,從而解決hash環(huán)偏斜問題
3.1.2.1 hash對象
Hash對象到后端服務(wù)器的映射關(guān)系:
3.1.2.2 一致性hash示意圖
后端服務(wù)器在線與離線的調(diào)度方式
#代碼實現(xiàn)
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance source
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
[root@client ~]#curl 10.0.0.7
10.0.0.18
3.2 uri
基于對用戶請求的URI的左半部分或整個uri做hash,再將hash結(jié)果對總權(quán)重進(jìn)行取模后肉渴,根據(jù)最終結(jié)果將請求轉(zhuǎn)發(fā)到后端指定服務(wù)器公荧,適用于后端是緩存服務(wù)器場景,默認(rèn)是靜態(tài)算法同规,也可以通過hash-type指定map-based和consistent稚矿,來定義使用取模法還是一致性hash。
注意:此算法基于應(yīng)用層捻浦,所以只支持 mode http 晤揣,不支持 mode tcp
#代碼實現(xiàn)
[root@rs1 ~]#cd /var/www/html
[root@rs1 html]#for i in {1..10};do echo test$i on 10.0.0.18 > test$i.html;done
[root@rs2 ~]#cd /var/www/html
[root@rs2 html]#for i in {1..10};do echo test$i on 10.0.0.28 > test$i.html;done
#uri一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance uri
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test2.html
test2 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.28
3.3 url_param
url_param對用戶請求的url中的 params 部分中的一個參數(shù)key對應(yīng)的value值作hash計算,并由服務(wù)器總權(quán)重相除以后派發(fā)至某挑出的服務(wù)器朱灿;通常用于追蹤用戶昧识,以確保來自同一個用戶的請求始終發(fā)往同一個real server,如果無沒key盗扒,將按roundrobin算法
#假設(shè)
url = http://www.baidu.com/foo/bar/index.php?key=value
#則
host = "www.baidu.com"
url_param = "key=value"
#代碼實現(xiàn)
#url_param一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance url_param userid
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test4.html?userid=gu
test4 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html?userid=gu
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7index.html?userid=gu
10.0.0.18
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
[root@client ~]#curl 10.0.0.7index.html?userid=wang
10.0.0.28
3.4 hdr
針對用戶每個http頭部(header)請求中的指定信息做hash跪楞,此處由 name 指定的http首部將會被取出并做hash計算缀去,然后由服務(wù)器總權(quán)重取模以后派發(fā)至某挑出的服務(wù)器,如果無有效值甸祭,則會使用默認(rèn)的輪詢調(diào)度缕碎。
#代碼實現(xiàn)
#hdr一致性hash
[root@proxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_web_80
bind 10.0.0.7:80
balance hdr(User-Agent)
hash-type consistent
server rs1 10.0.0.18:80 weight 1 check inter 3000 fall 2 rise 5
server rs2 10.0.0.28:80 weight 1 check inter 3000 fall 2 rise 5
server local 127.0.0.1:80 backup
[root@proxy ~]#systemctl reload haproxy.service
#測試
[root@client ~]#curl 10.0.0.7/index.html
10.0.0.18
[root@client ~]#curl 10.0.0.7/test1.html
test1 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test2.html
test2 on 10.0.0.18
[root@client ~]#curl 10.0.0.7/test3.html
test3 on 10.0.0.18
[root@client ~]#curl -A "IE"10.0.0.7/test4.html
test4 on 10.0.0.28
[root@client ~]#curl -A "Chrome18"10.0.0.7/test4.html
test4 on 10.0.0.18
[root@client ~]#curl -A "Chrome28"10.0.0.7/test4.html
test4 on 10.0.0.28
[root@client ~]#curl -A "firefox"10.0.0.7/test4.html
test4 on 10.0.0.18
3.5 rdp-cookie
rdp-cookie對windows遠(yuǎn)程桌面的負(fù)載,使用cookie保持會話池户,默認(rèn)是靜態(tài)咏雌,也可以通過hash-type指定map-based和consistent,來定義使用取模法還是一致性hash校焦。
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen m44_rdp_3389
bind 10.0.0.100:3389
mode tcp
balance rdp-cookie
hash-type consistent
server rdp1 10.0.0.200:3389
[root@haproxy ~]#systemctl reload haproxy..service
[root@haproxy ~]#ss -ntl #10.0.0.100:3389端口打開
#測試
windows命令行輸入mstsc
4 算法總結(jié)
#靜態(tài)
static-rr--------->tcp/http
first------------->tcp/http
#動態(tài)
roundrobin-------->tcp/http
leastconn--------->tcp/http
random------------>tcp/http
#以下靜態(tài)和動態(tài)取決于hash_type是否consistent
source------------>tcp/http
Uri--------------->http
url_param--------->http
hdr--------------->http
rdp-cookie-------->tcp
5 各種算法使用場景
first #使用較少
static-rr #做了session共享的 web 集群
roundrobin
random
leastconn #數(shù)據(jù)庫
source #基于客戶端公網(wǎng) IP 的會話保持
Uri--------------->http #緩存服務(wù)器赊抖,CDN服務(wù)商,藍(lán)汛寨典、百度氛雪、阿里云、騰訊
url_param--------->http #可以實現(xiàn)session保持
hdr #基于客戶端請求報文頭部做下一步處理
rdp-cookie #基于Windows主機(jī),很少使用
4耸成、使用haproxy的ACL實現(xiàn)基于文件后綴名的動靜分離
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
frontend m44_web_80
bind 10.0.0.100:80
###################### acl setting #########################
acl acl_static path_end -i .jpg .jpeg .png .gif .css .js .html .htm #基于文件后綴名
acl acl_php path_end -i .php
###################### acl hosts ##########################
use_backend static_hosts if acl_static
use_backend app_hosts if acl_php
default_backend app_hosts
#################### backend hosts ########################
backend static_hosts
server rs1 10.0.0.18:80 check
backend app_hosts
server rs2 10.0.0.28 check
[root@haproxy ~]#systemctl restart haproxy.service
#分別在后端兩臺主機(jī)準(zhǔn)備相關(guān)文件
[root@centos18 ~]#ls /var/www/html
index.html wang.jpg
[root@centos28 ~]#cat /var/www/html/test.php
<?php
echo "<h1>http://10.0.0.28/test.php</h1>\n";
?>
#測試
[root@client ~]#curl 10.0.0.100/wang.jpg
10.0.0.18
[root@client ~]#curl 10.0.0.100/test.php
10.0.0.28