在高併發網絡編程中,TIME_WAIT 是繞不開的話題。大量 TIME_WAIT 連接會佔用端口資源,導致「Address already in use」錯誤,嚴重限制服務吞吐量。本文從協議原理、內核實現、影響分析、優化方案四個維度,系統闡述如何正確應對。
主動發起關閉的一方(發送第一個 FIN)在收到對端 ACK 後,進入 TIME_WAIT 狀態,持續 2 MSL (Maximum Segment Lifetime)。Linux 內核固定為 60 秒(TCP_TIMEWAIT_LEN),不可通過 sysctl 修改。
LAST_ACK 狀態會重發 FIN。若無 TIME_WAIT,主動關閉方直接復用端口建立新連接,收到舊 FIN 會回 RST,導致新連接建立失敗。| 維度 | 影響 | 量化估算 |
|---|---|---|
| 端口槽位復用 | 四元組 (src/dst IP/port) 60 秒內不可復用 | 單 IP 約 28k 可用端口 → 理論上限 ~460 conn/s |
| 內核內存 | 每連接佔用 tcp_timewait_sock (168B) + 可能 inet_bind_bucket |
10 萬連接約 10-15 MB,現代服務器可忽略 |
| CPU 開銷 | 哈希表查找、定時器管理 | 極小,非瓶頸 |
net.ipv4.ip_local_port_range (如 1024-65535)。Connection: close,由服務端發起 FIN,TIME_WAIT 轉移到服務端(通常服務端端口固定、IP 固定,影響較小)。tcp_tw_reuse (僅客戶端有效)TIME_WAIT 連接可在 1 秒後被新的 外發連接 復用。tcp_timestamps (默認開啟)。tcp_tw_recycle (強烈不推薦生產環境)TIME_WAIT 回收 (3.5 RTO),對 入站/出站雙向生效。/etc/sysctl.d/99-tcp-tw.conf
# 客戶端/負載節點
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1 # 默認開啟,確保未關閉
# 服務端(不建議開 tw_recycle)
# net.ipv4.tcp_tw_recycle = 0
# 防止 TIME_WAIT 暴增導致內核拒絕新連接(默認 180000,可適當調大)
net.ipv4.tcp_max_tw_buckets = 262144
sysctl -p /etc/sysctl.d/99-tcp-tw.conf
設置 SO_LINGER 為 l_onoff=1, l_linger=0,close() 直接發 RST 而非 FIN,完全跳過 TIME_WAIT。但會導致:
僅適用於極端場景(如壓測工具、短連接探活),業務系統嚴禁使用。
TIME_WAIT 是 TCP 協議保證可靠性的必要機制,不要盲目關閉。tcp_tw_reuse,配合擴大端口範圍,解決 99% 場景。tcp_tw_recycle,依賴 tcp_max_tw_buckets 保護內核,現代硬件內存足夠承載。理解協議本質,才能在性能與可靠性之間找到最佳平衡點。