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

游戏卡顿白皮书 › L8 Socket 与协议

TCP 队头阻塞 Head-of-line blocking

原因 ID sk-hol · 主责 研发团队·服务器开发 · 配合 研发团队·客户端开发

在含图示和实验的完整版中打开此卡片 →

TCP 为了保证顺序,在重新收到丢失的那个包之前,不会把后面已经到达的数据包交给游戏。

起因 一个数据包丢失 → 结果 后面的包已经到了,却在接收缓冲区里等着 → 画面表现 先停顿,然后一下子全部放出来,表现为快进

症状
卡住, 快进
因素
丢包, 停顿
谁会遇到
只有我
何时出现
偶尔随机
负责方
主责 研发团队·服务器开发 · 配合 研发团队·客户端开发
研发团队要做的事
服务器:实时位置用 UDP,只有必不可少的内容走可靠传输,拆成多条流。客户端:网络处理改成与服务器相同的方式(UDP、分通道)。
数值参考
丢一个包至少停顿往返时间 + α,连重传也丢了则会停顿几百 ms 到几秒。
监控图上
断流后集中到达 · 每个连接的接收量、重传次数
查看位置
用服务器侧抓包(tcpdump、Wireshark)查看该玩家连接中的重传包及其前后的空档;全服看 nstat -az 中 TcpRetransSegs 的增量
确认依据
停顿区间以一个包的重传开始,重传包到达后,积压的数据被一次性处理(接收量先是 0,然后集中涌入)
排除依据
用 UDP 通信的游戏不适用。没有重传却停顿,看服务器 tick(“Tick 超出预算”)
确认手段
运维工具即可确认(无需游戏代码)

出处

  1. RFC 9293: Transmission Control Protocol (TCP) IETF
    TCP 是可靠的、保证顺序的字节流服务
  2. RFC 5681: TCP Congestion Control IETF
    通过 3 个重复 ACK 检测丢包并快速重传,否则等待重传定时器
  3. RFC 6298: Computing TCP's Retransmission Timer IETF
    重传定时器每超时一次就翻倍的退避
  4. net/ipv4/proc.c (Linux v6.12) Linux kernel
    nstat 显示的计数器名:Tcp 组的 RetransSegs(重传的报文段数)

相关原因

同一层:L8 Socket 与协议

其他层中同样导致“卡住”的原因

查看含图示和实验的原卡片