游戏卡顿白皮书 › TCP 重传的根本原因
RTO 设置与环境不匹配 RTO min too low or too high
原因 ID rt-rto-setting · 主责 运维团队·系统运维 · 配合 研发团队·服务器开发
在含图示和实验的完整版中打开此卡片 →
RTO 最小值调得太低,稍微晚一点就会产生虚假重传;默认值(200 ms)对游戏来说又太长,每丢一次包都要停顿很久。
起因 为数据中心场景把 RTO 最小值调得很低,或者在公网链路上原样使用默认值 → 结果 太低时瞬间的延迟也会引发大量重传,太高时每次丢包都要等很久 → 画面表现 用默认值时,丢一次包就卡住几百 ms 再快进;调得太低,卡住会缩短,但虚假重传激增,浪费线路
- 症状
- 卡住, 快进, 操作延迟
- 因素
- 延迟
- 谁会遇到
- 全服
- 何时出现
- 一直
- 负责方
- 主责 运维团队·系统运维 · 配合 研发团队·服务器开发
- 研发团队要做的事
- Linux 6.15 及以上时,考虑对游戏连接用 TCP_RTO_MAX_MS 降低 RTO 上限(放弃连接所需的时间也会变短,所以要同时用 TCP_USER_TIMEOUT 设定断线判定时间);只对服务器间的内部连接用 socket 选项 TCP_RTO_MIN_US(6.15 及以上)降低 RTO 最小值;考虑用 socket 选项 TCP_THIN_LINEAR_TIMEOUTS,只让游戏连接的连续 RTO 不再翻倍。
- 运维团队要做的事
- 只对服务器间的内部连接按路由降低 rto_min;公网链路保持默认值,用 RACK-TLP 和 thin stream 设置(tcp_thin_linear_timeouts)弥补。
- 数值参考
- Linux RTO = 往返时间 + max(200 ms, RTT 偏差×4)。每失败一次翻倍,最大 120 秒。Linux 6.15 及以上可以用 TCP_RTO_MAX_MS 把这个上限最低降到 1 秒。
- 监控图上
- 一直偏高 · 每个连接的 RTO,虚假 RTO 次数
- 查看位置
- 看服务器的 RTO 最小值设置(ip route show 的 rto_min,Linux 6.11 及以上还有 sysctl net.ipv4.tcp_rto_min_us)和 ss -ti 的 rto、rtt,并看 nstat 中 TcpExtTCPSpuriousRTOs 的增量
- 确认依据
- 在调低了最小值的服务器上,公网连接的 rto 紧贴 rtt,TcpExtTCPSpuriousRTOs 大量增加。保持默认值时,游戏连接的 rto 比 rtt 大 200 ms 以上,每丢一次包就停顿这么久
- 排除依据
- rto 符合默认算法(rtt + 200 ms 左右),虚假 RTO 也少,停顿却特别长,看连续丢包或恢复机制方面(“thin stream 恢复慢”“中间设备剥离 TCP 选项”)
- 确认手段
- 运维工具即可确认(无需游戏代码)
出处
- RFC 6298: Computing TCP's Retransmission Timer IETF
RTO = SRTT + max(G, 4·RTTVAR),建议最小 1 秒,每失败一次翻倍,如设最大值应不少于 60 秒 - include/net/tcp.h Linux kernel
Linux TCP_RTO_MIN 200 ms,TCP_RTO_MAX 120 秒 - net/ipv4/tcp_input.c Linux kernel
Linux RTO 为 SRTT + rttvar,rttvar 不会低于 RTO 最小值(默认 200 ms) - tcp: add the ability to control max RTO Linux kernel
新增 TCP_RTO_MAX_MS socket 选项(1~120 秒),从 Linux 6.15 起 - tcp: add sysctl_tcp_rto_min_us Linux kernel
新增整台服务器默认的 RTO 最小值 tcp_rto_min_us,从 Linux 6.11 起 - tcp: support TCP_RTO_MIN_US for set/getsockopt use Linux kernel
新增按 socket 设定 RTO 最小值的 TCP_RTO_MIN_US socket 选项,从 Linux 6.15 起 - IP Sysctl Linux kernel
tcp_rto_min_us 默认 200000(路由选项 rto_min 和 socket 选项 TCP_RTO_MIN_US 优先),tcp_rto_max_ms 1,000~120,000(默认 120,000),tcp_thin_linear_timeouts - ip-route(8) — Linux manual page iproute2
按路由的 rto_min 选项:与该目的地通信时的 RTO 最小值 - Thin-streams and TCP Linux kernel
用 TCP_THIN_LINEAR_TIMEOUTS 可以只对 thin stream 连接关闭指数退避 - tcp(7) — Linux manual page Linux man-pages
TCP_USER_TIMEOUT:等待未确认数据、直到关闭连接的时间 - ss(8) — Linux manual page iproute2
ss -i 的 rto(ms)和 rtt - SNMP counter Linux kernel
TcpExtTCPSpuriousRTOs:F-RTO 检测到的虚假 RTO
相关原因
同一层:TCP 重传的根本原因
其他层中同样导致“卡住”的原因
查看含图示和实验的原卡片