萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 電腦故障排除 >  >> 電腦常見故障 >> 無法連上網路

防火牆會話表滿載 vs 過早老化:TCP Keepalive 調教實戰解決連線中斷與延遲暴增

防火牆狀態檢測的兩難困境

狀態檢測防火牆需維護「會話表」記錄五元組(雙向 IP、Port、協議、方向、狀態)。會話表條目過多 → 查表延遲飆升;老化時間太短 → 長連線(資料庫、SSH、WebSocket、MQTT)被誤判為閒置而強制切斷。預設值常見 5 分鐘~1 小時,兩極端皆會造成生產事故。

經典案例:資料庫連線池 5 分鐘斷線之謎

  • Web Server → Firewall → DB Server,連線池閒置超過 5 分鐘。
  • 防火牆會話老化時間 = 5 分鐘 → 刪除會話條目。
  • 應用發送新查詢 → 防火牆無會話匹配 → 丟棄封包 → 應用拋出「Connection reset」或重連風暴。

為什麼單純調長老化時間會拖垮效能?

會話表採用雜湊表/樹狀結構,條目數達萬/十萬級時,查表、老化掃描、記憶體佔用皆線性增長。高併發場景下,CPU 花在掃描過期條目與鎖競爭的比例顯著上升,導致封包轉發延遲從亞毫秒級飆至數十毫秒甚至更高。

破解之道:調整 TCP Keepalive 讓「長連線自證存活」

RFC 1122 定義 TCP Keepalive 預設 2 小時(7200 秒)發送空 ACK 探針。關鍵洞見:只需在「伺服器端」啟用並縮短 Keepalive 間隔,Client 端完全不用動。

Linux 系統調整範例(永久生效)

# /etc/sysctl.d/99-tcp-keepalive.conf
net.ipv4.tcp_keepalive_time = 180      # 閒置 3 分鐘發送首次探針 (預設 7200)
net.ipv4.tcp_keepalive_intvl = 30      # 探針間隔 30 秒 (預設 75)
net.ipv4.tcp_keepalive_probes = 3      # 連續 3 次無回應才判定斷線 (預設 9)

套用:sysctl --system 或重開機。

Windows Server 調整(登錄檔)

路徑:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
新增 DWORD 值:
KeepAliveTime     = 180000   (毫秒,3 分鐘)
KeepAliveInterval = 30000    (毫秒,30 秒)
TcpMaxDataRetransmissions = 3  (重試次數)

重開機生效。只需在資料庫伺服器、API Gateway、MQTT Broker 等「被動接受長連線」的伺服器端設定即可,成百上千 Client 端零接觸。

效果驗證

  • 防火牆會話表條目數下降 60%~80%(僅保留真正活躍連線)。
  • 查表延遲恢復至亞毫秒級。
  • 長連線不再因防火牆老化中斷,應用層無感知。
  • 網路額外負載極低:每條閒置連線每 3 分鐘僅 1 個 60 bytes 探針封包。

補充策略:應用層心跳雙重保險

TCP Keepalive 僅能偵測「TCP 連線存活」,無法偵測「應用程式凍結」。建議在應用層協議(HTTP Keep-Alive、WebSocket Ping/Pong、MQTT PINGREQ、DB 連線池 validationQuery)同步啟用心跳,雙層防護。

防火牆端同步調整建議

  • 將 TCP 會話老化時間設為 Keepalive 總探測時間的 1.5~2 倍(如 3 分鐘 × 3 次 × 1.5 ≈ 14 分鐘),避免正常探針期間被誤刪。
  • 啟用「TCP 狀態檢測嚴格模式」檢查序號窗口,防止偽造封包重置會話。
  • 針對已知長連線埠(3306, 5432, 6379, 1883, 8883)建立獨立會話老化策略,不受全域預設影響。

核心心法:讓連線擁有者(Server)主動證明存活,而非讓中間設備(Firewall)被動猜測。這才是解決會話中斷與效能惡化的根本之道。

copyright © 萬盛學電腦網 all rights reserved