1. 題目與適用場景
一個長連線用戶端經過 NAT、負載平衡器與伺服器。網路中斷後,連線在作業系統中仍顯示已建立;團隊爭論應只開啟 TCP Keepalive,還是增加應用層 ping/pong。請比較兩種機制,給出偵測間隔、逾時、代理策略與重新連線動作。假設業務需要知道「工作階段是否仍能處理請求」,而不只是網卡是否可達。
2. 面試官考察點
- 是否能區分傳輸層探測與應用層可用性探測。
- 是否知道 TCP Keepalive 依賴核心計時器,預設值和中間設備行為不能直接當作業務 SLA。
- 是否能設計有時間預算的心跳、逾時、關閉與重新連線狀態機,避免誤判和風暴。
- 是否會把 NAT、代理閒置逾時、行動網路與伺服器負載納入端到端方案。
3. 回答前需要釐清的問題
- 要偵測的是網路路徑、TCP 對端程序,還是業務工作階段是否可用?
- 中間 NAT、閘道與負載平衡器的閒置連線逾時是多少?
- 連線承載的是可重放查詢,還是必須確認的命令與交易?
- 用戶端數量、可接受的額外頻寬和同時重連上限是多少?
4. 30 秒回答框架
TCP Keepalive 由核心送出探測,主要發現長時間閒置的 TCP 對端或路徑失效;應用層心跳由協定定義,能驗證對端應用仍可讀寫並回傳業務確認。我會先用連線狀態機定義健康、可疑、關閉和退避狀態,再按最短代理閒置時間設定心跳間隔。Keepalive 作為底層兜底,應用心跳負責業務 SLA;逾時後關閉舊連線,用帶抖動的指數退避重新連線並限制並發。
5. 分步驟深入解答
第一步:定義兩種機制的觀察對象
TCP Keepalive 在 socket 層工作。Linux tcp(7) 提供閒置時間、探測間隔和探測次數等參數;探測得到 ACK 只能說明 TCP stack 仍能回應,不代表應用完成認證、租約仍有效或請求能被處理。它適合發現沉默的半開連線並釋放核心資源。
應用層心跳是協定訊息,例如 ping 帶工作階段或能力資訊,伺服器用 pong 或含狀態的回應確認。它能發現事件迴圈卡住、租約過期、認證失效或伺服器過載等 TCP 看不見的問題,但會消耗應用 CPU、頻寬和連線配額。
第二步:用端到端時間預算設定參數
先找出最短中間設備閒置逾時 Tidle,再選擇小於它並留出抖動餘量的心跳間隔,例如 Thb <= Tidle / 2。應用回應截止時間 Tdeadline 要小於業務允許的失聯時間;連續 N 次失敗才判定連線死亡,避免一次丟包造成誤殺。TCP Keepalive 的閒置時間可以更長,作為無業務訊息時的底層兜底,不能取代應用 SLA。
第三步:設計狀態機和動作
連線建立後進入 healthy。送出心跳後進入 suspect,在截止時間內收到應用回應便回到 healthy;連續失敗就主動關閉 socket 並進入 backoff。退避使用指數增長加隨機抖動並設定上限;網路離線或頁面隱藏時暫停撥號,恢復後先做健康檢查。舊連線必須先關閉,避免兩條連線同時消費同一命令流。
第四步:依訊息語意恢復
通知可以允許遺失,重連後重新訂閱即可。寫入命令不能只依靠心跳確認:每個命令帶冪等鍵或序號,伺服器回傳明確確認,用戶端記錄最後連續確認點。重連後從游標重播或查詢狀態;若無法判斷命令是否執行,先讀取伺服器狀態再決定是否重試。
第五步:驗證中間設備和營運指標
用抓包或連線日誌確認心跳確實穿過 NAT、代理與負載平衡器。記錄心跳 RTT、逾時率、Keepalive 探測失敗、連線年齡、重連次數、退避時間和並發峰值。故障演練應覆蓋拔網線、NAT 回收、伺服器事件迴圈阻塞、認證過期與大規模同時斷線。只看 TCP 狀態為 ESTABLISHED 不足以證明業務可用。
6. 高品質示範回答
我會把兩種機制分層。TCP Keepalive 是核心探測,能發現長時間閒置的半開 TCP 連線,但 ACK 不等於應用能處理請求;應用層心跳能驗證協定、認證與租約,因此負責業務健康判斷。先量出最短 NAT 或負載平衡器閒置逾時,把心跳間隔設在約一半,並設定回應截止時間與連續失敗次數。連線狀態機在健康、可疑、關閉和帶抖動退避之間轉換,逾時先關閉舊連線再重連。通知重連後重新訂閱,命令使用冪等鍵和確認游標恢復。Keepalive 是無業務流量時的底層兜底,不能取代應用心跳或無限重試。
7. 常見錯誤
- 認為 TCP ACK 證明業務健康 → 核心可能回應但應用執行緒已卡死 → 使用應用層請求-回應心跳。
- 直接採用系統預設 Keepalive 參數 → 預設閒置時間可能超過代理逾時 → 依端到端時間預算設定。
- 每次漏一個心跳就重連 → 短暫丟包造成風暴 → 使用截止時間、連續失敗門檻與抖動退避。
- 只調整用戶端心跳 → NAT 或負載平衡器仍按更短閒置時間回收 → 同時核對所有中間設備。
- 重連後盲目重送寫入命令 → 可能重複扣款或建立資料 → 使用冪等鍵、確認點和狀態查詢。
8. 追問及應對
追問一:既然應用心跳更強,為什麼還要 TCP Keepalive?
應用可能長期沒有業務訊息,或協定實作失效。Keepalive 能在沉默期間發現底層路徑失效並釋放 socket;它是低層兜底,不能承擔業務確認。
追問二:心跳間隔應該越短越好嗎?
不是。間隔越短,偵測越快但 CPU、頻寬、行動裝置耗電與伺服器並發成本越高。先滿足中間設備閒置預算,再用故障演練驗證誤判率與偵測延遲,按連線類型分級設定。
追問三:大規模服務重啟後如何避免重連風暴?
用戶端使用指數退避與隨機抖動,伺服器按租戶或連線類型限流,必要時回傳重試時間。離線用戶端暫停撥號,恢復後分批建立連線,並監控重連峰值。