游戏卡顿白皮书 › L8 Socket 与协议
TCP RTO 与指数退避 RTO and exponential backoff
原因 ID sk-rto · 主责 研发团队·服务器开发 · 配合 研发团队·客户端开发
在含图示和实验的完整版中打开此卡片 →
重传每失败一次,等待时间就翻一倍,短暂的线路中断会变成长时间停顿。
起因 线路短暂中断,重传也接连失败 → 结果 到下一次尝试的间隔按 0.3 → 0.6 → 1.2 → 2.4 秒这样翻倍(以 ping 100 ms 为例) → 画面表现 线路只断了 1 秒,游戏却卡住 2 秒以上。断得更久,最终就会掉线
- 症状
- 卡住, 掉线
- 因素
- 丢包, 停顿
- 谁会遇到
- 只有我
- 何时出现
- 偶尔随机, 移动中/切换地图时
- 负责方
- 主责 研发团队·服务器开发 · 配合 研发团队·客户端开发
- 研发团队要做的事
- 服务器:响应心跳,一段时间收不到就主动清理连接(用 TCP_USER_TIMEOUT 让连接更早放弃);凭会话令牌接续会话;使用可靠 UDP。客户端:以较短间隔发送心跳,响应一断就尽快重连,不要等 TCP 重传。
- 数值参考
- Linux 的 RTO(重传等待时间)最小为“ping + 200 ms”,建立连接时从 1 秒起步。按默认设置(tcp_retries2=15),即使重传一直失败,也要约 15 分钟后才放弃连接。
- 监控图上
- 断流后集中到达 · 每个连接的 RTO、backoff,RTO 超时次数
- 查看位置
- 对停顿的连接用 ss -ti 看 rto(重传等待 ms)和 backoff(连续超时次数),全服看 nstat -az 中 TcpExtTCPTimeouts(重传定时器超时次数)的增量
- 确认依据
- 停顿连接的 backoff 在 1 以上,rto 已涨到秒级,且那个时刻 TCPTimeouts 增加
- 排除依据
- 重传都以快速重传结束、没有 RTO 超时,停顿就很短。这时看“TCP 队头阻塞”
- 确认手段
- 运维工具即可确认(无需游戏代码)
出处
- 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(200 ms),所以 RTO 至少为 RTT+200 ms - IP Sysctl Linux kernel
tcp_rto_min_us 默认 200 ms,连接请求的首个 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 与协议
其他层中同样导致“卡住”的原因
查看含图示和实验的原卡片