遊戲 Lag 白皮書 › TCP 重傳的根本原因
延遲飆升造成的不必要重傳 Spurious RTO from delay spikes
原因 ID rt-spurious-delay · 主要負責 外部(外部) · 協同 基礎設施團隊(伺服器基礎設施), 遊戲開發團隊(用戶端開發)
在含圖解與實驗的完整版中開啟卡片 →
封包沒有消失,只是短暫地很晚才到;但這段延遲比 RTO 長時,傳送端就會判斷為遺失而重傳。
為什麼 bufferbloat、Wi-Fi 省電、行動網路無線狀態切換、虛擬機器暫停,造成瞬間延遲達數百 ms → 於是 RTO 先到期而重傳,原本的封包也隨即抵達(接收端收到重複的封包) → 畫面上 定格與快轉是延遲飆升本身造成的。不必要的重傳幾乎不會拉長定格,只會推高重傳指標,因而被誤認為遺失
- 症狀
- 定格, 快轉, 輸入延遲
- 因素
- 延遲, 抖動
- 誰會遇到
- 只有我, 整個伺服器
- 何時
- 偶爾隨機發生, 閒置一段時間後
- 負責單位
- 主要負責 外部(外部) · 協同 基礎設施團隊(伺服器基礎設施), 遊戲開發團隊(用戶端開發)
- 遊戲開發團隊要做的事
- Android 10 以上的用戶端在遊戲中要求低延遲 Wi-Fi 模式(WIFI_MODE_FULL_LOW_LATENCY Wi-Fi lock,只在螢幕開啟且遊戲位於前景時生效),減少省電造成的延遲飆升。
- 基礎設施團隊要做的事
- 避免使用突發型(burstable)執行個體、不要把 RTO 最小值調得太低、保持 F-RTO 與時間戳記開啟(tcp_frto、tcp_timestamps)、重傳指標要與 nstat 的 TCPSpuriousRTOs、TCPDSACKRecv 一起看,以免誤認為遺失。
- 外部要做的事
- 為了減少延遲飆升本身,建議玩家在分享器使用 SQM、關閉 Wi-Fi 省電。
- 數值參考
- Linux 會用 F-RTO 偵測不必要的 RTO,有時也會撤回已降低的傳送量。可用 nstat 的 TCPSpuriousRTOs(判定為不必要 RTO 的次數)與 TCPDSACKRecv(接收端回報「已經收過」的次數)確認。
- 圖表上
- 偶爾隨機飆高 · RTT(ping)、不必要的 RTO 次數
- 查看位置
- 每 1 分鐘執行一次 nstat,一起查看 TcpExtTCPTimeouts(RTO 到期)、TcpExtTCPSpuriousRTOs、TcpExtTCPDSACKRecv、TcpExtTCPLostRetransmit 的增加量。有封包擷取時用 Wireshark 篩選條件 tcp.analysis.spurious_retransmission
- 符合的跡象
- RTO 增加時,TcpExtTCPSpuriousRTOs 或 TcpExtTCPDSACKRecv 也一起增加,同一時間 RTT 飆到數百 ms。接收端的封包擷取中,原本的封包與重傳的封包都有抵達
- 不符合的跡象
- TcpExtTCPSpuriousRTOs 與 DSACK 沒有變化,TcpExtTCPLostRetransmit(連重送的封包也再次遺失)卻增加時,是實際遺失。RTT 沒有飆高、只有 DSACK 一直很多時,是「封包亂序造成的不必要快速重傳」
- 確認方式
- 用基礎設施工具確認(不需要遊戲程式碼)
出處
- RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP IETF
F-RTO:利用 RTO 之後收到的 ACK,判斷該次 RTO 是否不必要 - RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks IETF
行動網路的延遲飆升(換手、鏈路復原等)會引發不必要的 TCP 逾時與重傳,並使壅塞視窗縮小 - RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP IETF
DSACK:接收端回報重複收到的封包,讓傳送端知道哪些重傳是不必要的 - SNMP counter Linux kernel
TcpExtTCPSpuriousRTOs(F-RTO 偵測到的不必要 RTO)、TcpExtTCPDSACKRecv(收到的 DSACK 數)、TcpExtTCPLostRetransmit(SACK 回報重送的封包再次遺失的次數) - IP Sysctl Linux kernel
tcp_frto 預設開啟(對 RTT 波動大的無線網路有利),tcp_timestamps 預設 1 - RFC 6298: Computing TCP's Retransmission Timer IETF
要避免不必要的重傳,最小 RTO 必須夠大的依據(建議至少 1 秒) - WifiManager Android (Google)
WIFI_MODE_FULL_LOW_LATENCY(API 29,Android 10):只在連上 AP、螢幕開啟且 App 位於前景時才生效的低延遲 Wi-Fi lock - net/ipv4/proc.c Linux kernel
nstat 顯示的計數器名稱 TCPTimeouts、TCPSpuriousRTOs、TCPDSACKRecv、TCPLostRetransmit - net/ipv4/tcp_timer.c Linux kernel
TCPTimeouts 在重傳計時器(RTO)到期時增加 - nstat(8) — Linux manual page iproute2
nstat 預設顯示自上次執行以來的增加量 - Display Filter Reference: Transmission Control Protocol Wireshark
tcp.analysis.spurious_retransmission 顯示篩選條件
相關原因
同一層:TCP 重傳的根本原因
同一症狀(定格)在其他層的原因
查看含圖解與實驗的完整版卡片