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