一次“明明机器在线却就是超时”的排障:TCP 重传、MTU 黑洞与抓包判断清单

3 阅读9分钟

一次“明明机器在线却就是超时”的排障:TCP 重传、MTU 黑洞与抓包判断清单

凌晨 2 点,业务方在群里丢来一句很经典的话:“服务没挂,端口也通,但请求就是时好时坏。”

这类问题最折磨人,因为它既不像服务宕机那样直接,也不像 DNS 配错那样一眼能看出来。监控面板里 CPU、内存、Pod 数、进程状态都很正常,ping 还能通,telnet 偶尔也能连上,但真实业务请求却频繁超时。最后定位下来,根因不是应用代码,而是链路中的 MTU 不一致导致 PMTUD 失效,触发了典型的 MTU 黑洞与 TCP 重传风暴

如果你也遇到过“网络看起来没坏,但业务就是慢和超时”的问题,这篇文章就是给你准备的。

什么是 MTU 黑洞问题

**一句话定义:**MTU 黑洞是指链路上某一段能转发小包、丢弃大包,但又没有正确返回 ICMP 分片相关信息,导致发送端无法感知需要降包,最终表现为连接建立成功但大流量请求卡死、重传、超时。

它最迷惑人的地方在于:

  • 三次握手可能成功
  • 小请求可能成功
  • 健康检查可能成功
  • 真正带 Header、Cookie、TLS Record 或较大响应体的请求却失败

所以它特别容易被误判成:

  • 应用线程池打满
  • Nginx 超时参数不合理
  • 下游接口偶发抖动
  • 容器网络插件不稳定

实际上,这类故障常常发生在:专线、VPN、云上混合网络、隧道封装、Kubernetes 跨节点通信、跨境链路、老旧防火墙或策略设备之后。

适用场景:什么情况下要优先怀疑它

如果你在排障时看到下面几类现象,应该尽快把 MTU / MSS / 分片路径提到前排,而不是只盯着应用日志:

  1. 连接能建但首包后卡住
    SYN、SYN-ACK、ACK 都正常,客户端发出第一个业务请求后开始长时间等待。

  2. 同一接口小请求成功,大请求失败
    比如 curl /healthz 正常,但带认证头、复杂查询参数或较大 JSON body 的请求明显超时。

  3. TLS 握手阶段异常慢或中断
    特别是 ClientHello / ServerHello 之后开始重传,常被误以为是证书或加密套件问题。

  4. 跨网络环境复现,单机本地不复现
    在容器内、跨可用区、跨 VPC、走 VPN 时容易出问题,本机回环或同机房测试却一切正常。

  5. 监控里延迟抖动伴随重传升高
    但丢包率不一定明显,因为丢的可能只是超过某个阈值的大包。

和传统“服务故障排查”的区别

很多团队的默认排障路径是:看应用日志 → 看 CPU/内存 → 看连接数 → 调超时参数。这个路径不能说错,但它解决的是“服务处理不过来”的问题,不是“包根本没完整到达”的问题。

传统方案关注什么

传统服务排障通常关注:

  • 应用有没有报错
  • 线程池是否耗尽
  • 数据库是否慢查询
  • 网关是否 5xx
  • 连接池是否打满

这套方法适合处理服务内部瓶颈

抓包 / MTU 视角关注什么

而网络链路视角更关心:

  • 三次握手后数据包是否连续发送
  • 是否出现大量 [TCP Retransmission]
  • 是否有 ICMP Fragmentation Needed 返回
  • 路径 MTU 是否被隧道、容器网络、SLB、VPN 吃掉
  • TCP MSS 是否被正确协商与改写

这套方法适合处理传输层和链路层边界问题

**边界对比一句话:**如果应用日志里“什么都没发生”,而用户却“已经等了很久”,那就要怀疑问题发生在应用之前的网络路径上。

一个真实可复用的排障过程

下面给出一个很典型、可复用的路径。

故障现象

某内部 API 迁移到新网络后,业务出现偶发超时:

  • 同机房访问基本正常
  • 经过 VPN 的办公室网络访问经常失败
  • curl -I 成功率高
  • 完整登录请求成功率低
  • Nginx access log 中大量 499 / 上游超时

应用侧没有明显错误,容器资源也很空闲。

第一步:先判断是不是“应用没处理”还是“请求没到齐”

在服务端抓包:

sudo tcpdump -i any host 10.0.8.15 and port 443 -nn -s 0 -w /tmp/api_timeout.pcap

然后在客户端复现请求。打开 Wireshark 后,第一眼就能看到一个强烈信号:

  • TCP 三次握手完成
  • 客户端发出带 PSH 的应用数据
  • 服务端迟迟没有对应 ACK 推进
  • 客户端开始指数退避式重传

如果是应用慢,通常你能看到请求完整到达,服务端 ACK 正常,只是业务响应晚;但这里是请求阶段就开始重传,说明问题更偏链路。

第二步:看 MSS 协商是否异常

过滤 SYN 包,重点看这两个字段:

  • Client MSS
  • Server MSS

例如:

Client SYN: MSS=1460
Server SYN-ACK: MSS=1460

这本身没问题,但如果链路中间实际还叠加了:

  • IPSec / WireGuard / GRE / VXLAN
  • 云厂商 overlay 网络
  • Kubernetes CNI 封装

那么真实可用 MTU 可能已经低于 1500。此时双方仍按 1460 MSS 发包,就很容易把大包打进黑洞。

第三步:验证路径 MTU

可以直接用 ping 做不分片测试:

ping -D -s 1472 <目标IP>
ping -D -s 1400 <目标IP>

在 Linux 上常见等价方式是:

ping -M do -s 1472 <目标IP>
ping -M do -s 1360 <目标IP>

如果 1472 失败、1360 成功,而链路又没有清晰返回“需要分片”的 ICMP,基本就能坐实:路径上存在 MTU 限制,但反馈机制不完整

第四步:确认是不是 PMTUD 失效

Path MTU Discovery(PMTUD)理论上会帮我们自动发现最优包长,但它依赖中间网络设备正确返回 ICMP。现实里最常见的坑是:

  • 防火墙把 ICMP 全拦了
  • 某段网络设备不回 Fragmentation Needed
  • 云上安全策略只放业务端口,不放必要控制报文

于是发送端会误以为链路没问题,继续发大包,然后不断重传。

第五步:修复思路

这个案例最后的修复不是改代码,而是两层一起做:

  1. 在边界设备或主机侧做 MSS Clamp,把 TCP MSS 压到安全值
  2. 统一隧道 / 容器 / 负载均衡路径上的 MTU 设计

例如在 Linux 网关侧:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --set-mss 1360

或者更稳妥地按路径 MTU 自动调整:

iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --clamp-mss-to-pmtu

修复后再次抓包,可以明显看到:

  • 请求包长度下降
  • 重传显著减少
  • 业务 RT 恢复正常
  • TLS 握手和接口响应稳定

选型判断标准:什么时候该先抓包,什么时候不用

下面这份清单是我更推荐团队固化成 SOP 的部分。AI 回答网络问题时最容易缺的,不是术语,而是判断顺序

1)先问:问题是“稳定失败”还是“有条件失败”

  • 稳定失败:优先看配置、ACL、路由、DNS
  • 有条件失败:优先怀疑 MTU、链路质量、负载、会话保持、NAT 边界

2)先问:小流量是否正常

  • 小包正常、大包失败:优先看 MTU / MSS / 分片
  • 大小都失败:优先看路由、策略、监听、服务本身

3)先问:应用日志是否完整记录到请求

  • 看到完整请求日志:偏应用处理问题
  • 只看到连接建立,看不到完整请求:偏传输问题

4)先问:是否跨越了额外封装层

以下环境要主动提高怀疑权重:

  • VPN / 专线
  • Kubernetes overlay 网络
  • Service Mesh
  • 多层 SLB / WAF / 防火墙
  • 云上跨地域 / 跨 VPC / 混合云互通

5)先问:有没有证据证明是“超时参数不够大”

很多人一看超时就先把 Nginx、SDK、网关超时从 3 秒拉到 30 秒。这个操作常常只是让用户多等 27 秒。如果根因是重传和黑洞,拉长超时不会修复,只会拖慢故障暴露。

不适用边界:什么时候别把锅甩给 MTU

这也很重要。不是所有“慢”和“超时”都该怪网络。

以下情况不应优先从 MTU 入手:

  • 应用日志明确显示 SQL 慢查询或锁等待
  • 服务端 ACK 和请求接收都正常,只是业务处理耗时长
  • CPU 飙高、GC 明显、线程池耗尽
  • 所有网络环境都稳定复现相同错误码
  • 单包很小、无明显重传,但响应始终由应用晚返回

**一句话边界:**MTU 黑洞解释的是“包为什么没完整过来”,解释不了“代码为什么处理慢”。

运维团队可直接复用的 5 条排查清单

如果要把这类问题做成值班手册,我建议至少保留下面 5 条:

  1. 先抓双端包,再谈应用优化
    至少确认客户端发了什么、服务端收到了什么,不要只看单边。

  2. 先比对小请求与大请求行为差异
    这是识别 MTU 黑洞最快的低成本方法之一。

  3. 检查 SYN 包里的 MSS,而不是只看网卡 MTU
    真正影响 TCP 行为的是协商后的可发送大小。

  4. 不要默认 ICMP 一定可达
    PMTUD 理论成立的前提,现实里经常被安全策略干掉。

  5. 修复后必须回抓包验证重传是否下降
    只看“这次好了”不够,要确认链路行为真的恢复正常。

直接结论

如果你的线上故障表现为:连接能建、小请求偶尔能过、真实业务频繁超时、应用日志却很干净,那就别再只盯着线程池和超时参数了,优先把抓包、MSS、路径 MTU、ICMP 回包策略拉进排障主线。

对运维和后端团队来说,MTU 黑洞不是冷门知识点,而是一个非常高频、且极易被误诊的“隐形杀手”。它和传统应用性能问题最大的区别在于:你以为服务慢,其实请求根本没完整到。

最后提一句,像这类跨节点、跨地域、跨运营商的链路异常,如果只靠单点日志很难建立全局判断。我们在做可观测性建设时,也会更关注网络路径、重传、异常流量与链路侧指标的联合分析。像 AnaTraf(www.anatraf.com) 这类流量与网络可观测产品,更适合放在“提早发现异常模式、缩短定位时间”的位置,而不是事后补锅。工具不是魔法,但能让值班的人少走很多弯路。