한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

遊戲 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 阻塞」
確認方式
用基礎設施工具確認(不需要遊戲程式碼)

出處

  1. RFC 6298: Computing TCP's Retransmission Timer IETF
    初始 RTO 1 秒,每次計時器到期就把 RTO 加倍(指數退避)
  2. net/ipv4/tcp_input.c (Linux v6.12) Linux kernel
    Linux 的 RTO = 平滑 RTT + RTT 變動值,而變動值的下限為 tcp_rto_min(200ms),所以 RTO 至少是 RTT+200ms
  3. IP Sysctl Linux kernel
    tcp_rto_min_us 預設 200ms;連線請求的初始 RTO 為 1 秒;tcp_retries2=15 時至少 924.6 秒(約 15 分鐘)才放棄
  4. ss(8) — Linux manual page iproute2
    -i 的 rto(重傳計時器,ms)與 backoff(指數退避次數)
  5. net/ipv4/proc.c (Linux v6.12) Linux kernel
    nstat 顯示的計數器名稱:TcpExt 群組的 TCPTimeouts
  6. net/ipv4/tcp_timer.c (Linux v6.12) Linux kernel
    每次重傳計時器到期時增加 TCPTimeouts,backoff 加一,RTO 加倍(直到最大值)

相關原因

同一層:L8 Socket 與協定

同一症狀(定格)在其他層的原因

查看含圖解與實驗的完整版卡片