一次TCP TIME_WAIT連接數(shù)過多告警處理
問題回顧
客戶反饋收到如下告警,主機TCP timewait連接數(shù)過多
prometheus告警表達式
node_sockstat_TCP_tw > 50000
收到連接數(shù)過多的告警并不代表一定會產(chǎn)生生產(chǎn)問題,此時要關(guān)注負載是否直線上升,連接數(shù)一直無法釋放,如果出現(xiàn)此情況,則需要及時處理,避免造成生產(chǎn)環(huán)境宕機。
連接數(shù)數(shù)據(jù)來源:/proc/net/sockstat
線上場景中,持續(xù)的高并發(fā)場景
- 一部分 TIME_WAIT 連接被回收,但新的 TIME_WAIT 連接產(chǎn)生,新產(chǎn)生的連接數(shù)超過釋放的速度;
- 一些極端情況下,會出現(xiàn)大量的 TIME_WAIT 連接。
Think:上述大量的 TIME_WAIT 狀態(tài) TCP 連接,有什么業(yè)務(wù)上的影響嗎?
Nginx 作為反向代理時,大量的短鏈接,可能導(dǎo)致 Nginx 上的 TCP 連接處于 time_wait 狀態(tài):
每一個 time_wait 狀態(tài),都會占用一個「本地端口」,上限為 65535
當大量的連接處于 time_wait 時,新建立 TCP 連接會出錯,address already in use : connect 異常
Tips:TCP 本地端口數(shù)量,上限為 65535(6.5w),這是因為 TCP 頭部使用 16 bit,存儲「端口號」,因此約束上限為 65535。
圖片
- time_wait 狀態(tài)的影響
TCP 連接中,「主動發(fā)起關(guān)閉連接」的一端,會進入 time_wait 狀態(tài)
time_wait 狀態(tài),默認會持續(xù) 2 MSL(報文的最大生存時間)
time_wait 狀態(tài)下,TCP 連接占用的端口,無法被再次使用
TCP 端口數(shù)量,上限是 6.5w(65535,16 bit)
net.ipv4.ip_local_port_range = 1024 65000 #端口數(shù)和這個參數(shù)有關(guān)系
大量 time_wait 狀態(tài)存在,會導(dǎo)致新建 TCP 連接會出錯,address already in use : connect 異常
大量的連接會導(dǎo)致服務(wù)器資源使用上升
- 現(xiàn)實場景
服務(wù)內(nèi)部調(diào)用過多,優(yōu)化業(yè)務(wù)模式,也可以是連接關(guān)閉方式需要優(yōu)化
Nginx 反向代理場景中,可能出現(xiàn)大量短鏈接,服務(wù)器端可能存在
- 解決思路
1、服務(wù)器端允許 time_wait 狀態(tài)的 socket 被重用
2、縮減 time_wait 時間,設(shè)置為 1 MSL(即,2 mins)
解決方案
TCP連接數(shù)統(tǒng)計腳本
#!/bin/sh
for i in /proc/* ;
do
if [ -d $i/fd ];then
echo $i $(ls $i/fd -l | grep socket: |wc -l)
fi
done
通過這個腳本可以統(tǒng)計出當前分配連接數(shù)的進程,通過進程可以找到對應(yīng)的服務(wù),如果是服務(wù)關(guān)閉連接的姿勢不對,業(yè)務(wù)方優(yōu)化即可
在業(yè)務(wù)側(cè)解決此問題之前,我們可以通過操作系統(tǒng)的內(nèi)核參數(shù)緩解此問題
方案
修改配置文件/etc/sysctl.conf
1、允許將TIME_WAIT狀態(tài)的socket重新用于新的TCP連接
net.ipv4.tcp_tw_reuse = 1 #默認為0,表示關(guān)閉,如果為0,修改為1
2、快速回收TIME_WAIT狀態(tài)的socket
net.ipv4.tcp_tw_recycle = 1 #修改為1,默認為0
3、修改time_wait連接數(shù)的回收時間
cat /proc/sys/net/ipv4/tcp_fin_timeout #查看默認的MSL值
net.ipv4.tcp_fin_timeout = 30 #如果為60,修改為30s回收
最后sudo sysctl -p 使配置生效即可,從修改前后的效果上可以看到,timewait的回收明顯加快了