游戏卡顿白皮书 › TCP 重传的根本原因
乱序导致的虚假快速重传 Reordering triggers spurious fast retransmit
原因 ID rt-reorder · 主责 运维团队·网络运维 · 配合 运维团队·系统运维
在含图示和实验的完整版中打开此卡片 →
数据包经过多条路径或聚合链路时顺序被打乱,接收方会用重复 ACK 通知“有包缺失”,发送方就把好好的包又发一遍。
起因 按包分配路径的设备、按包分摊的 LAG(链路聚合)、路径切换的瞬间,都会打乱顺序 → 结果 后面的包先到,累积 3 个重复 ACK → 快速重传 → 画面表现 稀疏往来的游戏包几乎不受影响。人多处的大块状态更新和更新包下载会变慢,偶尔一卡一卡
- 症状
- 一卡一卡, 操作延迟
- 因素
- 抖动
- 谁会遇到
- 特定地区/运营商, 全服
- 何时出现
- 一直, 人多的时候
- 负责方
- 主责 运维团队·网络运维 · 配合 运维团队·系统运维
- 运维团队要做的事
- 网络:把按包分流改成按连接分流(ECMP、LAG 按地址和端口做哈希)。服务器/OS:使用 RACK(基于时间判断丢包,不怕乱序;通过 DSACK 检测到虚假重传时会自动放宽乱序容忍范围);查看 Linux 为每个连接自动估算的乱序程度(ss -ti 的 reordering 值,初始值为 tcp_reordering=3)。
- 监控图上
- 一直偏高 · 乱序检测次数,DSACK 接收数
- 查看位置
- 看 nstat 的 TcpExtTCPSACKReorder、TcpExtTCPTSReorder(检测到乱序的次数)和 TcpExtTCPDSACKRecv;按连接看 ss -ti 的 reordering(不为 3 时才显示)和 reord_seen。抓包中用 Wireshark 过滤条件 tcp.analysis.out_of_order
- 确认依据
- 乱序计数器和 DSACK 不分时段持续上升,经过特定路径或设备的连接 reordering 值大于 3。接收方抓包中后面的包先到,前面的包随后也到达
- 排除依据
- 乱序计数器不变,TcpExtTCPLostRetransmit 增加,就是真实丢包。只在 RTT 跳变的瞬间 DSACK 增加,看“延迟飙升导致的虚假重传”
- 确认手段
- 运维工具即可确认(无需游戏代码)
出处
- RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection IETF
按包分配路径会打乱顺序,后面的包有 3 个以上先到时,TCP 会做虚假快速重传 - RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm IETF
用区分流的头部字段的哈希值选择路径的 ECMP(按流分流) - RFC 5681: TCP Congestion Control IETF
收到第三个重复 ACK 时快速重传 - RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP IETF
RACK 基于时间判断丢包,不怕乱序;收到 DSACK 后会延长乱序容忍时间(reo_wnd) - IP Sysctl Linux kernel
tcp_reordering 初始值 3(每个连接自动调整,最高到 tcp_max_reordering),tcp_recovery 中的 RACK 设置 - misc/ss.c iproute2
连接的 reordering 值与默认值 3 不同时,ss -ti 显示 reordering:值;连接遇到过乱序时显示 reord_seen:次数 - SNMP counter Linux kernel
TcpExtTCPSACKReorder、TcpExtTCPTSReorder(检测到乱序),TcpExtTCPDSACKRecv(收到的 DSACK 数),TcpExtTCPLostRetransmit(重传的包又丢失) - include/uapi/linux/tcp.h Linux kernel
tcp_info 的 tcpi_reord_seen:连接遇到乱序的次数 - Display Filter Reference: Transmission Control Protocol Wireshark
tcp.analysis.out_of_order 显示过滤器
相关原因
同一层:TCP 重传的根本原因
其他层中同样导致“一卡一卡”的原因
查看含图示和实验的原卡片