LVS是一種非常高效的負載均衡軟體實作,尤其是DR模式。但實際部署需要考慮real server的健康狀況,并應該根據real server的健康狀況或擴容縮容需求及時更新LVS的配置。但是動态修改LVS配置,對正在運作的用戶端會有什麼影響呢?考慮到這些問題對LVS做了個全組合測試。
參考網上的流行配置。如下
LVS伺服器:
點選(此處)折疊或打開
echo 1 > /proc/sys/net/ipv4/ip_forward
ifconfig eth0:0 ${vip} broadcast ${vip} netmask 255.255.255.255 up
ipvsadm -A -t ${vip}:${port} -s rr
ipvsadm -a -t ${vip}:${port} -r ${realserver}
...
後端real server:
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
ifconfig lo:0 ${vip} broadcast ${vip} netmask 255.255.255.255 up
用LVS做MySQL的負載均衡,測試結果如下:
是否存在lvs realserver配置項
mysql服務
用戶端操作
結果
結果判斷
存在
啟動
建立連接配接
成功
OK
執行sql
停止
ERROR 2003 (HY000): Can't connect to MySQL server on '10.27.113.51' (111)
mysql> select 1;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 9911
Current database: *** NONE ***
mysql程序死掉的時候會給直接用戶端發個F包,這樣用戶端可以檢出連接配接切斷。
已執行sql等待服務端傳回
mysql> select sleep(20);
ERROR 2013 (HY000): Lost connection to MySQL server during query
mysql程序死掉的時候會給直接用戶端發個F包,這樣用戶端可以檢出連接配接切斷,停止等待。
不存在
成功(有其它real server可選)或失敗(無其它real server可選)
[root@srdsdevapp69 ~]# mysql -h 10.27.113.51 -e "select @@server_id";
用戶端一直等待ack包。處于這個狀态時,再加上lvs的realserver可以恢複。
+---+
| 1 |
1 row in set (5 min 25.57 sec)
注意tcpdump包
17:20:22.310061 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:22.510941 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:22.912934 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:23.716944 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:25.324920 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:28.540935 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:34.972918 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:20:47.836934 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:21:13.564932 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:22:05.021017 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:23:47.932941 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:25:47.932934 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [P.], seq 126:139, ack 295, win 123, length 13
17:25:47.934196 IP 10.27.113.51.mysql > srdsdevapp69.40776: Flags [P.], seq 295:351, ack 139, win 29, length 56
17:25:47.934287 IP srdsdevapp69.40776 > 10.27.113.51.mysql: Flags [.], ack 351, win 123, length 0
NG
正常執行,因為mysql的回報不經過lvs,隻要用戶端的包發出去了,lvs的配置修改了也不會影響這個包的響應。
mysql> select sleep(10);
+-----------+
| sleep(10) |
| 0 |
1 row in set (10.00 sec)
上面倒數第二個測試結果我認為是有問題的。試想,如果我要叢集收縮删除一個背景伺服器,如果直接從LVS的realserver清單裡删,就會導緻那些還連在上面的用戶端下次發SQL時會一直等待。
4. 改進後的配置
後經調查,通過在LVS伺服器上設定下面的核心參數可解決問題。上面的場景下,用戶端發SQL時會立刻錯誤傳回。
echo 1 > /proc/sys/net/ipv4/vs/expire_nodest_conn
5. 最後
LVS預設行為的初衷好像是期待背景伺服器發生故障後從清單中剔除,然後等背景伺服器恢複之後再加進來。這段時間讓用戶端等待,可以使故障對用戶端透明。實際上這基本是做不到的,背景伺服器故障再恢複後,提供服務的程序已經不是原來的程序了,無法繼續使用之前的連接配接。是以LVS還不如把立刻錯誤傳回作為預設行為。