當 HAProxy 後端 real server 縮擴容時,需要修改 HAProxy 配置文件,我們希望 HAProxy 既能夠加載到最新配置,又能夠:
- 不重啓 HAProxy;
- 不影響之前現有客戶端到 HAProxy 的連接。
解決方法:
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
測試案例如下:
一、修改 HAProxy 配置文件
配置項 proxy_tw 下,tw_proxy_1 / tw_proxy_2 各自對應一個 Twemproxy 服,而每個 Twemproxy 服提供相同的功能,即爲兩個主備 Redis 集羣提供分片和代理功能。
現在,我們暫時註釋 tw_proxy_2,然後重啓 HAProxy 服務。
二、編寫 python 測試腳本:redis_test.py
腳本功能:事先通過 HAProxy 創建一個到後端 Redis 的連接(HAProxy -> tw_proxy_1 -> Redis),然後在一個無限循環中,每隔一秒鐘,嘗試獲取鍵 area 的值。
#coding:utf -8
import redis
import time
import datetime
if __name__ == "__main__":
r=redis.Redis(host='192.168.177.222',password='www.wave.com',db=0,port=16001)
value_pre = None
value_cur = None
while(1):
now_int = datetime.datetime.now()
now_str = now_int.strftime("%Y-%m-%d %H:%M:%S")
value_cur = r.get('area')
print now_str + ' ' + value_cur
value_pre = value_cur
time.sleep(1)
三、模擬更新前的客戶端連接
運行 python 腳本:
python redis_test.py
腳本運行結果:
訪問 HAProxy 管理平臺,可以看到當前 tw_proxy_1 上存在一個會話:
四、模擬新增服務器
1、修改 HAProxy 配置文件,取消註釋 tw_proxy_2
2、重新加載配置
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
查看進程:
我們可以看到,進程 ID 未發生變更,說明 HAProxy 尚未重啓,但比之前多了一個進程(27084),這個就是剛剛爲了重新加載配置文件而執行的命令。
3、繼續觀察第三章節執行的 python 測試腳本
可以看到,配置文件更新前後 ,腳本一直在源源不斷地輸出正確結果,說明配置文件更新沒有影響現有客戶端到 HAProxy 的連接。
4、HAProxy 管理平臺
可以看到,proxy_tw 下目前有 tw_proxy_1 和 tw_proxy_2 兩個實體,且當前會話個數爲 0(實際爲 1)。
五、模擬更新後的客戶端連接
另開一個控制檯,運行腳本:redis_test.py。腳本輸出結果:
訪問 HAProxy 管理平臺,可以看到當前 tw_proxy_1 上存在一個會話(實際上有2個:舊 / 新客戶端):
六、模擬下架服務器
現在我們嘗試下架 tw_proxy_1 所在的服務器。
1、HAProxy 管理平臺中,設置 tw_proxy_1 進入 DRAIN (排幹)模式,即新的請求不再接收,舊的請求繼續等待執行完畢。
執行結果:
2、另開一個控制檯,運行腳本:redis_test.py。測試 DRAIN 模式。
可以看到,tw_proxy_2 當前有一個會話。
3、修改 HAProxy 配置文件,取消註釋 tw_proxy_1
4、重新加載配置
/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)
查看進程:
我們可以看到,比之前又多了一個進程(30581),27084 和 30581 都是爲了重新加載配置文件而執行的命令。
同時可以看到,proxy_tw 下目前只有 tw_proxy_2 一個實體,且當前會話數爲 0(實際上有三個)。
5、殺死 tw_proxy_1 進程
現在,我們把去要下架的服務器上,把 tw_proxy_2 對應的 Twemproxy 服務殺死。
6、觀察 HAProxy 管理平臺
可以看到,tw_proxy_2 當前有兩個會話(實際上應該有三個)。
7、觀察 python 腳本控制檯
觀察前面三個運行 python 測試腳本的控制檯,可以看到三個控制檯均在源源不斷地輸出正確值。
8、再次觀察進程
可以看到,相比前面第 4 小節,HAProxy 進程 ID 已變更。
9、模擬下架後的新的客戶端連接
另開一個控制檯,運行腳本:redis_test.py。腳本輸出結果:
反覆刷新 HAProxy 管理平臺,查看 tw_proxy_1 當前會話情況,可以看到兩種結果:一種是,當前會話數爲 2,最近會話創建時間是在 13 分36秒之前;另一種是,當前會話數爲 1,最近會話創建時間是在 3分鐘11秒之前。
10、再次模擬下架後的新的客戶端連接
反覆刷新 HAProxy 管理平臺,查看 tw_proxy_1 當前會話情況,可以看到兩種結果:一種是,當前會話數爲 1,最近會話創建時間是在 9 分21秒之前;另一種是,當前會話數爲 3,最近會話創建時間是在 2分鐘33秒之前。
11、按開啓順序,依次終止各 python 測試腳本
除了第三個,即將 tw_proxy_1 設置爲 DRAIN 模式後運行的測試腳本,關閉其他 4 個,都會使 HAProxy 管理平臺中 tw_proxy_2 的當前會話數 - 1。
查看進程,可以看到,進程:27084(即第一次爲了重新加載配置文件而執行的命令) 已經消失。