在上一篇文章中,分析了haproxy的stick table特性和用法,其中特性之一也是很實用的特性是stick table支持在haproxy多個節點之間進行複製(replication)。 本文僅討論如何配置實現stick table的複製功能,不考慮在什麼環境下實現它,以及它的雙主模型如何配置 ...
在上一篇文章中,分析了haproxy的stick table特性和用法,其中特性之一也是很實用的特性是stick table支持在haproxy多個節點之間進行複製(replication)。
本文僅討論如何配置實現stick table的複製功能,不考慮在什麼環境下實現它,以及它的雙主模型如何配置。
本文實驗環境:
1.stick table複製特性
只要設置好haproxy的節點組,haproxy就會自動將新插入的、剛更新的stickiness記錄通過TCP連接推送到節點組中的非本地節點上。這樣一來,stickiness記錄不會丟失,即使某haproxy節點出現了故障,其他節點也能將客戶端按照粘性映射關係引導到正確的後端伺服器上。
由於每條stickiness記錄占用空間都很小(平均最小50位元組,最大166位元組,由是否記錄額外統計數據以及記錄多少來決定占用空間大小),使得即使在非常繁忙的環境下多個節點之間推送都不會出現壓力瓶頸和網路阻塞(可以按節點數量、stickiness記錄的大小和平均併發量來計算每秒在網路間推送的數據流量)。
它不像被人詬病的session複製(copy),因為session複製的數據量比較大,而且是在各應用程式伺服器之間進行的。而一個稍大一點的核心應用,提供服務的應用程式伺服器數量都不會小,這樣複製起來很容出現網路阻塞。
此外,stick table還可以在haproxy重啟時,在新舊兩個進程間進行複製,這是本地複製。當haproxy重啟時,舊haproxy進程會和新haproxy進程建立TCP連接,將其維護的stick table推送給新進程。這樣新進程不會丟失粘性信息,和其他節點也能最大程度地保持同步,使得其他節點只需要推送該節點重啟過程中新增加的stickiness記錄就能完全保持同步。
如果後端使用了session共用,在大多數情況下沒必要在代理層實現會話保持。如果此時使用stick table,一般只是為了收集統計數據進行採樣調查,但這樣的狀態統計數據無需在各節點之間進行複製。
2.如何定義haproxy節點成員
haproxy提供了peers
指令,用於定義節點組,peer
指令用於定義節點組中的成員。
例如,定義本文測試環境的節點組:
peers my_peers # 節點組名
peer haproxy1 192.168.100.59:12138 # 定義對端名稱,以及和對端建立tcp連接的埠,用於推送stickiness記錄
peer haproxy2 192.168.100.54:12138
peer haproxy3 192.168.100.42:12138
然後在stick-table
指令中引用節點組。例如:
stick-table type ip size 100k expire 5m peers my_peers
註意,應當讓每個haproxy節點的節點組內容一致,然後使用haproxy命令的"-L"選項指定本地節點成員,這樣方便管理每個節點和本地節點。
haproxy -D -L haproxy1 -f /etc/haproxy/haproxy.cfg
如果不指定"-L",則在解析配置文件時將預設以主機名作為本地節點名進行解析,但很可能它不會定義在peers
中,因此會報錯。
因此,如果要實現stick table的複製,還想使用sysV或systemctl管理haproxy服務,需要修改這些服務管理腳本,在啟動、重啟和語法檢查項上加上"-L"選項。例如,systemd的haproxy服務管理腳本改為如下內容:
[root@xuexi ~]# cat /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
EnvironmentFile=/etc/sysconfig/haproxy
ExecStartPre=/usr/sbin/haproxy -L haproxy2 -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy-systemd-wrapper -L haproxy2 -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid $OPTIONS
ExecReload=/usr/sbin/haproxy -L haproxy2 -f /etc/haproxy/haproxy.cfg -c -q
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
[Install]
WantedBy=multi-user.target
另外個人建議,每個節點要麼完全使用sysV、systemctl管理haproxy的啟動、停止,要麼完全使用haproxy命令手動管理服務的啟動和停止,否則可能會出現記錄不同步的現象。至今沒找到會出現這個問題的原因。
3.完成配置
如下,是每個haproxy節點的配置文件內容。
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 20000
user haproxy
group haproxy
daemon
stats socket /var/run/haproxy.sock mode 600 level admin
spread-checks 2
peers mypeers
peer haproxy1 192.168.100.59:12138
peer haproxy2 192.168.100.54:12138
peer haproxy3 192.168.100.42:12138
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
timeout http-request 2s
timeout queue 3s
timeout connect 1s
timeout client 10s
timeout server 2s
timeout http-keep-alive 10s
timeout check 2s
maxconn 18000
frontend http-in
bind *:80
mode http
log global
default_backend dynamic_group
backend dynamic_group
stick-table type string len 32 size 5k expire 5m peers mypeers
stick on req.cook(PHPSESSID)
stick store-response res.cook(PHPSESSID)
balance roundrobin
option http-server-close
option httpchk GET /index.php
option redispatch
http-check expect status 200
server app1 192.168.100.60:80 check rise 1 maxconn 3000
server app2 192.168.100.61:80 check rise 1 maxconn 3000
然後分別在3個節點上啟動haproxy,註意加上"-L"選項。
haproxy -D -L haproxy1 -f /etc/haproxy/haproxy.cfg # exec on haproxy1
haproxy -D -L haproxy2 -f /etc/haproxy/haproxy.cfg # exec on haporxy2
haproxy -D -L haproxy3 -f /etc/haproxy/haproxy.cfg # exec on haproxy3
分別在haproxy1、haproxy2、haproxy3上監控stick table。如果下麵命令執行失敗,見查看stick table信息。
watch -n 1 'echo "show table dynamic_group" | socat unix:/var/run/haprox.sock -'
由於上面的配置文件中,stick table中存儲和匹配的記錄是響應報文中名為PHPSESSID的cookie,因此在瀏覽器上測試時,能實現會話粘性。但如果使用curl命令進行測試,由於curl每次執行結束進程就退出,無法緩存cookie,因此curl的每次請求都是新連接。此處正好利用curl這一點特性,來生成多個stickiness記錄,方便觀察stick table記錄推送的情況。
找一臺Linux主機,分別對三個haproxy節點進行5次curl請求。
ip1=192.168.100.59
ip2=192.168.100.54
ip3=192.168.100.42
for i in $ip1 $ip2 $ip3;do
for j in `seq 1 5`;do
curl http://$i/index.php &>/dev/null
usleep 500000
done
done
以下是截取自三個節點的stick table內容。
###################### haproxy1 ########################
# table: dynamic_group, type: string, size:5120, used:15
0x1551cc4: key=1t1lr3s5s7pm4tuu3476c40jk3 use=0 exp=286311 server_id=2
0x1551f04: key=3m3o6qkfvk8l4lenk0k8to2bd6 use=0 exp=288500 server_id=2
0x1551904: key=8bg6ej7md7453sp0rrgi5vsiu7 use=0 exp=281350 server_id=1
0x1552144: key=9c4lf1tncd290mjl7vnjafnqe2 use=0 exp=287418 server_id=2
0x1552744: key=b3gqn2i3emi43rfh3i8t0jhln4 use=0 exp=283523 server_id=1
0x15519c4: key=cskoqa8vbb7fbac4eko27hnk70 use=0 exp=281897 server_id=2
0x1550c54: key=ejjgpe1j99nv7hqmnlpib5osq6 use=0 exp=286867 server_id=1
0x1550fc4: key=immqb6ocsq8m5982o28hatk6c2 use=0 exp=285187 server_id=2
0x1550e44: key=lg78n74u0dj51m3cvkn9qhce66 use=0 exp=287953 server_id=1
0x15522c4: key=livn0t62bthpfvp5motknhb934 use=0 exp=284620 server_id=1
0x1551b44: key=mhkh0c4lpisr9kgdb3ggmplpk1 use=0 exp=285745 server_id=1
0x1552384: key=ovfoprd6p91sjbf22qo5jjd4u0 use=0 exp=289035 server_id=1
0x1552204: key=rvt3fnhr51sfrqu1aefjceqlu4 use=0 exp=282978 server_id=2
0x1550d84: key=snkm72pvasr36ut39qopd3jmb1 use=0 exp=282442 server_id=1
0x1552084: key=ucj2pkve527nt39mejp1n7jdu5 use=0 exp=284084 server_id=2
###################### haproxy2 ########################
# table: dynamic_group, type: string, size:5120, used:15
0x7fa77ec4c8a4: key=1t1lr3s5s7pm4tuu3476c40jk3 use=0 exp=278032 server_id=2
0x7fa77ec4d4e4: key=3m3o6qkfvk8l4lenk0k8to2bd6 use=0 exp=280404 server_id=2
0x7fa77ec4c2a4: key=8bg6ej7md7453sp0rrgi5vsiu7 use=0 exp=272658 server_id=1
0x7fa77ec4c424: key=9c4lf1tncd290mjl7vnjafnqe2 use=0 exp=279232 server_id=2
0x7fa77ec4be24: key=b3gqn2i3emi43rfh3i8t0jhln4 use=0 exp=275012 server_id=1
0x7fa77ec4c4e4: key=cskoqa8vbb7fbac4eko27hnk70 use=0 exp=273251 server_id=2
0x7fa77ec4c724: key=ejjgpe1j99nv7hqmnlpib5osq6 use=0 exp=278635 server_id=1
0x7fa77ec4d2a4: key=immqb6ocsq8m5982o28hatk6c2 use=0 exp=276814 server_id=2
0x7fa77ec4c964: key=lg78n74u0dj51m3cvkn9qhce66 use=0 exp=279812 server_id=1
0x7fa77ec4d664: key=livn0t62bthpfvp5motknhb934 use=0 exp=276201 server_id=1
0x7fa77ec4d7e4: key=mhkh0c4lpisr9kgdb3ggmplpk1 use=0 exp=277418 server_id=1
0x7fa77ec4c1e4: key=ovfoprd6p91sjbf22qo5jjd4u0 use=0 exp=280984 server_id=1
0x7fa77ec4d724: key=rvt3fnhr51sfrqu1aefjceqlu4 use=0 exp=274422 server_id=2
0x7fa77ec4c664: key=snkm72pvasr36ut39qopd3jmb1 use=0 exp=273842 server_id=1
0x7fa77ec4d424: key=ucj2pkve527nt39mejp1n7jdu5 use=0 exp=275620 server_id=2
###################### haproxy3 ########################
# table: dynamic_group, type: string, size:5120, used:15
0x1372c24: key=1t1lr3s5s7pm4tuu3476c40jk3 use=0 exp=276198 server_id=2
0x1372e64: key=3m3o6qkfvk8l4lenk0k8to2bd6 use=0 exp=278387 server_id=2
0x1372864: key=8bg6ej7md7453sp0rrgi5vsiu7 use=0 exp=271237 server_id=1
0x1373964: key=9c4lf1tncd290mjl7vnjafnqe2 use=0 exp=277304 server_id=2
0x1373f64: key=b3gqn2i3emi43rfh3i8t0jhln4 use=0 exp=273410 server_id=1
0x1372924: key=cskoqa8vbb7fbac4eko27hnk70 use=0 exp=271784 server_id=2
0x13723e4: key=ejjgpe1j99nv7hqmnlpib5osq6 use=0 exp=276753 server_id=1
0x13726e4: key=immqb6ocsq8m5982o28hatk6c2 use=0 exp=275073 server_id=2
0x1372564: key=lg78n74u0dj51m3cvkn9qhce66 use=0 exp=277840 server_id=1
0x1373ae4: key=livn0t62bthpfvp5motknhb934 use=0 exp=274507 server_id=1
0x1372aa4: key=mhkh0c4lpisr9kgdb3ggmplpk1 use=0 exp=275631 server_id=1
0x1373ba4: key=ovfoprd6p91sjbf22qo5jjd4u0 use=0 exp=278922 server_id=1
0x1373a24: key=rvt3fnhr51sfrqu1aefjceqlu4 use=0 exp=272865 server_id=2
0x13724a4: key=snkm72pvasr36ut39qopd3jmb1 use=0 exp=272330 server_id=1
0x13738a4: key=ucj2pkve527nt39mejp1n7jdu5 use=0 exp=273971 server_id=2
結果符合預期目標,每個表都有15條stickiness,且它們的key和對應的server_id完全相同。
有了stick table的複製功能,在沒有session共用的情況下,為架構設計多提供了幾種方案。至於如何選擇,需要考慮與其配合的軟體特性。特別適用的一種情況是,在haproxy前端使用LVS代理時,由於LVS只能4層負載,很可能將同一客戶端調度到不同的haproxy節點上,如果使用stick table複製,就不用擔心haproxy不能將客戶端引導到同一後端伺服器上的問題。另一種使用stick table複製的場景是結合keepalived實現雙主模型代理不同服務時,為了會話保持也高可用,可以使用stick table的複製保證粘性記錄不丟失。
回到Linux系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
回到網站架構系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7576137.html
回到資料庫系列文章大綱:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
轉載請註明出處:http://www.cnblogs.com/f-ck-need-u/p/8565998.html
註:若您覺得這篇文章還不錯請點擊右下角推薦,您的支持能激發作者更大的寫作熱情,非常感謝!