狀態檢測防火牆需維護「會話表」記錄五元組(雙向 IP、Port、協議、方向、狀態)。會話表條目過多 → 查表延遲飆升;老化時間太短 → 長連線(資料庫、SSH、WebSocket、MQTT)被誤判為閒置而強制切斷。預設值常見 5 分鐘~1 小時,兩極端皆會造成生產事故。
會話表採用雜湊表/樹狀結構,條目數達萬/十萬級時,查表、老化掃描、記憶體佔用皆線性增長。高併發場景下,CPU 花在掃描過期條目與鎖競爭的比例顯著上升,導致封包轉發延遲從亞毫秒級飆至數十毫秒甚至更高。
RFC 1122 定義 TCP Keepalive 預設 2 小時(7200 秒)發送空 ACK 探針。關鍵洞見:只需在「伺服器端」啟用並縮短 Keepalive 間隔,Client 端完全不用動。
# /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 或重開機。
路徑:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
新增 DWORD 值:
KeepAliveTime = 180000 (毫秒,3 分鐘)
KeepAliveInterval = 30000 (毫秒,30 秒)
TcpMaxDataRetransmissions = 3 (重試次數)
重開機生效。只需在資料庫伺服器、API Gateway、MQTT Broker 等「被動接受長連線」的伺服器端設定即可,成百上千 Client 端零接觸。
TCP Keepalive 僅能偵測「TCP 連線存活」,無法偵測「應用程式凍結」。建議在應用層協議(HTTP Keep-Alive、WebSocket Ping/Pong、MQTT PINGREQ、DB 連線池 validationQuery)同步啟用心跳,雙層防護。
核心心法:讓連線擁有者(Server)主動證明存活,而非讓中間設備(Firewall)被動猜測。這才是解決會話中斷與效能惡化的根本之道。