大量短連接導致haproxy服務器端口耗盡

現象

現象1:在haproxy中間件層查看netstat會有大量的time_wait,大概有幾萬個以上


現象2:查看haproxy日誌會有部分顯示端口耗盡

Jan  9 14:59:04 127.0.0.1 haproxy[37]: Connect() failed for backend ha-proxy: no free ports.
Jan  9 14:59:04 127.0.0.1 haproxy[38]: Connect() failed for backend ha-proxy: no free ports.
Jan  9 14:59:04 127.0.0.1 haproxy[38]: Connect() failed for backend ha-proxy: no free ports.
Jan  9 14:59:04 127.0.0.1 haproxy[38]: Connect() failed for backend ha-proxy: no free ports.
Jan  9 14:59:04 127.0.0.1 haproxy[38]: Connect() failed for backend ha-proxy: no free ports.
Jan  9 14:59:04 127.0.0.1 haproxy[35]: Connect() failed for backend ha-proxy: no free ports.

現象3:mysql連接偶爾報錯

ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

現象4:登錄mysql以後show processlist會存在部分unauthenticated user,reading  from net


故障原因

短時間內大量的短連接導致haproxy端口耗盡,通過查看cat /proc/sys/net/ipv4/ip_local_port_range 的數值可得知當前可使用的端口範圍,我這裏默認是32768到61000;即使將其調整到1024到65535,在大量短連接情況下效果也是很有限的,因爲處於time_wait狀態的端口沒法複用。

爲何會出現大量的time_wait:因爲tcp連接斷開時,主動發起tcp的一方會處於time_wait,而這個持續時間由內核參數/proc/sys/net/ipv4/tcp_fin_timeout控制,我這裏是60s,也就是說,我的可用端口數量是65535-1024=28232,那我平均每秒的新建連接數超過28232/60=470時就必然會出現端口耗盡的情況;假如我只調整端口範圍的話,那我平均每秒的新建連接數(65535-1024)/60=1075時也會出現端口耗盡的情況,提升空間不是很大

如何查看haproxy的每秒新建連接數:有兩種方法,第一種是簡單地過濾某一秒的haproxy的日誌行數,每新建一個連接,haproxy日誌都會加一行記錄;另外一種方法是使用socat打印當前haproxy的各種信息(haproxy開了多進程模式以後貌似不準),下面的信息就顯示當前每秒新建連接337個,進程啓動以後歷史最大爲1172個

echo "show info"| socat stdio /opt/udb/instance/haproxy/35d96a08-c230-4a32-9de5-5fe6b80eff46/stats |grep -i conn
Maxconn: 6000
Hard_maxconn: 6000
CurrConns: 170
CumConns: 1195526325
ConnRate: 337
ConnRateLimit: 0
MaxConnRate: 1172

優化方法

優化方法有好幾種,大概以下
1 業務層使用長連接
2 修改內核參數/proc/sys/net/ipv4/tcp_tw_reuse,將其改爲1,並確保客服端和服務器端的/proc/sys/net/ipv4/tcp_timestamps也爲1,這樣就可以複用處於time_wait狀態的端口。由於時間戳是精確到秒的,這樣設置以後,haproxy能夠承受的每秒最大短連接數量就是端口數量了,即28232
3 mysql前端加memcache或者redis緩存,減少每秒打開的連接數


參考
https://www.haproxy.com/blog/haproxy-high-mysql-request-rate-and-tcp-source-port-exhaustion/




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章