由於最近做微服務化,原有的haproxy通過檢測應用的check.jsp來進行應用健康狀態檢查,
發佈版本時,通過mv check.jsp check.jsp.bak,讓應用下線。
但是微服務spring-boot工程都是jar包,雖然可以通過7z命令來進行jar包內的文件重命名,或者刪除,這樣總感覺很low,破壞了jar包的完整性,存在一定的操作風險。雖然spring-boot有優雅停機功能,但是問題是,進行後端的應用優雅停機後,與haproxy的健康檢查到應用下線存在一定時間間隔,這一段時間內,有可能會導致請求分發到已經優雅停機的應用上,一般優雅停機後的應用接受到請求後,會引起請求等待,造成應用響應慢的假象。tomcat的connect.pause()方法並沒有關閉socket端口,而是引起等待。
既然haproxy作爲前端負載,爲何不直接改變負載均衡上的應用狀態呢?
1.haproxy 配置global nbproc 3。
global
log 127.0.0.1 local0
maxconn 40000
chroot /usr/local/haproxy
user haproxy
group haproxy
daemon
nbproc 3
defaults
log global
option dontlognull
retries 3
option redispatch
maxconn 400000
timeout connect 5000
timeout client 50000
timeout server 50000
listen admin_status
mode http
bind 0.0.0.0:18800
stats enable
stats uri /admin_status
stats auth admin:admin
stats admin if TRUE #開啓stats頁面的操作應用狀態的功能。
option httplog
此時打開haproxy的stats頁面,刷新頁面可以得到3個不同狀態的頁面。
其中pid=xxx(process #1,nbproc=3)
其中process #1標示當前頁面是第一個haproxy內核進程。每次刷新頁面,haproxy根據算法隨機返回3個進程中的其中一個進程的stats頁面。
此時我們選擇應用然後進行下線,set state to MAINT,請求會隨機分發到3個進程中的其中一個進程進行應用下線。如果要把3個進程中的應用狀態都改掉,就要看運氣了。
顯然這不是我們想要的。
翻閱相關文檔發現有兩種可行的方法。
https://www.cnblogs.com/276815076/p/6992557.html
https://blog.csdn.net/weixin_34007020/article/details/93011764
方法1:通過socat與3個進程進行通信,然每個進程都下線同一個應用。
haproxy的配置
global
log 127.0.0.1 local0
maxconn 400000
chroot /usr/local/haproxy
user haproxy
group haproxy
daemon
nbproc 3
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
stats socket /var/lib/haproxy/haproxy.sock3 mode 600 level admin process 3
下線操作:
echo "disable server app/staff_200_3" | socat stdio /var/lib/haproxy/haproxy.sock1
echo "disable server app/staff_200_3" | socat stdio /var/lib/haproxy/haproxy.sock2
echo "disable server app/staff_200_3" | socat stdio /var/lib/haproxy/haproxy.sock3
執行命令之後刷新到3個頁面發現都下線了。
方法2:定義多個stats端口,每個端口綁定進程。
global
log 127.0.0.1 local0
maxconn 400000
chroot /usr/local/haproxy
user haproxy
group haproxy
daemon
nbproc 3
listen admin_status1
mode http
bind 0.0.0.0:18801
stats enable
stats uri /admin_status
stats auth admin:admin
stats admin if TRUE
option httplog
bind-proccess 1
listen admin_status2
mode http
bind 0.0.0.0:18802
stats enable
stats uri /admin_status
stats auth admin:admin
stats admin if TRUE
option httplog
bind-process 2
listen admin_status3
mode http
bind 0.0.0.0:18803
stats enable
stats uri /admin_status
stats auth admin:admin
stats admin if TRUE
option httplog
登陸3個stats頁面進行操作。分別進行下線。
還有一個問題,我們軟下線時,已經進入應用的請求能夠響應完畢嘛?我們可以在後端應用寫一個Thread.sleep(1000)來模擬慢響應,經過測試發現已經進入的應用可以正常響應。