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

游戏卡顿白皮书 › TCP 重传的根本原因

连接请求(SYN)重传 SYN retransmission on connect

原因 ID rt-syn · 主责 研发团队·服务器开发 · 配合 运维团队·系统运维, 运维团队·网络运维, 研发团队·客户端开发

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

连接请求因连接队列(backlog)溢出或被防火墙拦截而丢失时,客户端操作系统会从 1 秒后开始,以逐渐拉长的间隔重发。

起因 维护结束后连接涌入,服务器连接队列溢出,或防火墙、DDoS 防护丢弃 SYN → 结果 客户端操作系统从 1 秒后开始按固定间隔重传 SYN(旧版 Linux 为 1 秒 → 2 秒 → 4 秒) → 画面表现 点击连接后延迟正好是 1 秒、3 秒这样的整秒数,一直失败就会连不上/无限加载

症状
连不上/无限加载
因素
丢包
谁会遇到
全服, 特定地区/运营商
何时出现
刚登录/维护结束后
负责方
主责 研发团队·服务器开发 · 配合 运维团队·系统运维, 运维团队·网络运维, 研发团队·客户端开发
研发团队要做的事
服务器:调大 listen 的 backlog 参数(与 somaxconn 一起);让游戏服务器及时调用 accept;登录排队系统。客户端:拉长连接重试间隔(随机打散)。
运维团队要做的事
服务器/OS:用 nstat 的 TcpExtListenOverflows、TcpExtListenDrops 和日志中的“Possible SYN flooding”警告确认服务器连接队列是否溢出;调大 somaxconn(与 listen 参数一起);启用 SYN Cookie。网络:放宽防火墙、DDoS 防护的 SYN 限制。
数值参考
Linux(包括 Android)的第一次 SYN 重传在 1 秒后。旧内核此后间隔每次翻倍,在第 1、3、7、15 秒……时重发,6.5 及以上版本则在 1、2、3、4、5 秒重发五次,之后再翻倍(7、11、19 秒……)(tcp_syn_linear_timeouts=4)。Android 手机即使升级了系统,往往还在用出厂时的内核,所以即使 Android 版本相同,不同机型也可能不一样。无论哪种,全部失败后约 2 分钟放弃。Windows 视版本和设置从 1 秒或 3 秒开始拉长,重发次数为 2~4 次,20~30 秒就放弃(该 PC 的值可用 netsh int tcp show global 的 Max SYN Retransmissions 查看)。
监控图上
开服/维护后激增 · 连接尝试数,连接队列溢出数
查看位置
看服务器 nstat 中的 TcpExtListenOverflows、TcpExtListenDrops 和 dmesg 中的“Possible SYN flooding on port”警告,用 ss -lnt 看监听 socket 的 Recv-Q(等待 accept 的连接数)是否达到 Send-Q(backlog 上限)。用服务器侧抓包确认 SYN 是否到达、是否回了 SYN-ACK
确认依据
维护结束后连接涌入时 TcpExtListenOverflows 增加,Recv-Q 紧贴 Send-Q。抓包中同一客户端的 SYN 以秒级间隔重复到来,服务器却不响应
排除依据
SYN 没到服务器,服务器计数器也不变,就是前端防火墙或 DDoS 防护丢弃了,看该设备的 SYN 限制和丢弃日志。服务器已回 SYN-ACK 而连接仍慢,就是回程方向丢包
确认手段
运维工具即可确认(无需游戏代码)

出处

  1. include/net/tcp.h Linux kernel
    首个 RTO TCP_TIMEOUT_INIT = 1 秒(RFC 6298 的初始值)
  2. RFC 6298: Computing TCP's Retransmission Timer IETF
    初始 RTO 1 秒,每次重传翻倍
  3. IP Sysctl Linux kernel
    tcp_syn_retries 默认 6,tcp_syn_linear_timeouts 默认 4(SYN RTO 依次为 1、1、1、1、1、2、4……),最后一次重传在第 67 秒,第 131 秒放弃,somaxconn 默认 4096,tcp_syncookies 默认 1
  4. tcp: make the first N SYN RTO backoffs linear Linux kernel
    把 SYN 重传的前几次改为固定间隔的提交,从 Linux 6.5 起(默认值 4 沿用 macOS、iOS 的做法)
  5. Android common kernels Android (Google)
    5.10~6.18 的通用内核同时获得支持,旧平台版本的内核(例如 android14-6.1)可用于新 Android 设备的出厂或升级
  6. TcpMaxConnectRetransmissions Microsoft
    旧版 Windows 默认值:SYN 重传 2 次,首次等待 3 秒,之后每次翻倍,最后一次重传后再等两倍时间才放弃(3+6+12=21 秒)
  7. TCP/IP connectivity issues troubleshooting Microsoft
    SYN 重传次数因操作系统而异,可用 netsh int tcp show global 的 Max SYN Retransmissions 查看
  8. listen(2) — Linux manual page Linux man-pages
    listen 的 backlog 参数会被 somaxconn 截断(Linux 5.4 起默认 4096,之前为 128)
  9. SNMP counter Linux kernel
    accept 队列(全连接队列)满时丢弃 SYN,TcpExtListenOverflows、TcpExtListenDrops 一起增加;TcpExtTCPSynRetrans
  10. net/ipv4/tcp_input.c Linux kernel
    “Possible SYN flooding on port …”日志消息
  11. net/ipv4/tcp_diag.c Linux kernel
    对监听 socket 而言,ss 的 Recv-Q 是等待 accept 的连接数,Send-Q 是 backlog 上限

相关原因

同一层:TCP 重传的根本原因

其他层中同样导致“连不上/无限加载”的原因

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