遊戲 Lag 白皮書 › L8 Socket 與協定
TCP RTO 與指數退避 RTO and exponential backoff
原因 ID sk-rto · 主要負責 遊戲開發團隊(伺服器開發) · 協同 遊戲開發團隊(用戶端開發)
在含圖解與實驗的完整版中開啟卡片 →
每次重傳又失敗,等待時間就加倍,於是線路短暫中斷會變成長時間停住。
為什麼 線路短暫中斷,重傳也接連失敗 → 於是 到下一次嘗試的等待時間以 0.3 → 0.6 → 1.2 → 2.4 秒逐次加倍(以 ping 100ms 計) → 畫面上 線路只斷了 1 秒,遊戲卻停住 2 秒以上。斷得更久最後就會斷線
- 症狀
- 定格, 斷線
- 因素
- 遺失, 停滯
- 誰會遇到
- 只有我
- 何時
- 偶爾隨機發生, 移動中/切換地圖時
- 負責單位
- 主要負責 遊戲開發團隊(伺服器開發) · 協同 遊戲開發團隊(用戶端開發)
- 遊戲開發團隊要做的事
- 伺服器:回應心跳封包,一段時間沒收到就主動清理連線(用 TCP_USER_TIMEOUT 縮短放棄連線前的等待時間),用 session token 接續連線,採用可靠 UDP。用戶端:以短間隔送出心跳封包,沒有回應時不要等 TCP 重傳,儘快重新連線。
- 數值參考
- Linux 的 RTO(重傳等待時間)最小為「ping + 200ms」,建立連線時從 1 秒開始。預設設定(tcp_retries2=15)下,即使重傳一直失敗,也要約 15 分鐘後才會放棄連線。
- 圖表上
- 中斷後一次湧入 · 每條連線的 RTO 與 backoff、RTO 到期次數
- 查看位置
- 用 ss -ti 看停住的連線的 rto(重傳等待 ms)與 backoff(連續到期次數);整個伺服器則看 nstat -az 的 TcpExtTCPTimeouts(重傳計時器到期次數)增加量
- 符合的跡象
- 停住的連線 backoff 為 1 以上,rto 已變大到以秒計,那個時間點 TCPTimeouts 增加
- 不符合的跡象
- 重傳以快速重傳完成、沒有 RTO 到期時,停住的時間很短。這時是「TCP HOL 阻塞」
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
出處
- RFC 6298: Computing TCP's Retransmission Timer IETF
初始 RTO 1 秒,每次計時器到期就把 RTO 加倍(指數退避) - net/ipv4/tcp_input.c (Linux v6.12) Linux kernel
Linux 的 RTO = 平滑 RTT + RTT 變動值,而變動值的下限為 tcp_rto_min(200ms),所以 RTO 至少是 RTT+200ms - IP Sysctl Linux kernel
tcp_rto_min_us 預設 200ms;連線請求的初始 RTO 為 1 秒;tcp_retries2=15 時至少 924.6 秒(約 15 分鐘)才放棄 - ss(8) — Linux manual page iproute2
-i 的 rto(重傳計時器,ms)與 backoff(指數退避次數) - net/ipv4/proc.c (Linux v6.12) Linux kernel
nstat 顯示的計數器名稱:TcpExt 群組的 TCPTimeouts - net/ipv4/tcp_timer.c (Linux v6.12) Linux kernel
每次重傳計時器到期時增加 TCPTimeouts,backoff 加一,RTO 加倍(直到最大值)
相關原因
同一層:L8 Socket 與協定
同一症狀(定格)在其他層的原因
查看含圖解與實驗的完整版卡片