network - troubleshooting

12. 网络排障

0. 本章先解决什么问题

网络问题最容易被一句话糊弄过去:

网络不通。
网络慢。
服务挂了。

这些说法都太粗。真正排障时,需要把一次通信拆成层次、阶段、证据和假设。

本章要建立一个可复用的方法:

先定位失败阶段
再映射到协议层
再收集最小证据
最后验证假设

学完以后,你应该能把“访问不了”“超时”“偶发慢”“连接被重置”“只有某些用户失败”拆成可以逐步检查的问题。

请求耗时瀑布

这张图怎么读

这张图把“网络慢”拆成可观察的阶段:DNS、TCP、TLS、请求发送、服务处理、首字节、响应下载。排障时不要先争论原因,先拿到每段耗时,慢在哪一段,问题空间就会立刻缩小。

1. 第一原则:先问失败发生在哪个阶段

一次典型 HTTPS 请求可以拆成:

  1. 构造 URL
  2. DNS 解析
  3. 路由选择
  4. ARP/下一跳交付
  5. TCP 连接
  6. TLS 握手
  7. HTTP 请求发送
  8. 服务处理
  9. HTTP 响应返回
  10. 连接复用或关闭

每个阶段失败,应用看到的现象不同。

阶段常见现象
DNS域名解析失败、解析慢、解析到旧 IP
路由/链路目标不可达、丢包、跨网段不通
TCPrefused、connect timeout、reset
TLS证书错误、握手失败、协议不兼容
HTTP4xx、5xx、重定向、缓存异常
应用处理首字节慢、业务错误、响应体异常
连接管理空闲断开、CLOSE_WAIT、TIME_WAIT、连接池耗尽

排障第一步不是猜原因,而是定位阶段。

2. 第二原则:区分“可达”和“可用”

不同测试证明不同层次:

测试证明什么不证明什么
ping 通某种 ICMP 路径可达目标端口开放、应用可用
TCP 端口能连传输层入口可达HTTP/TLS/业务正确
TLS 握手成功安全通道能建立应用返回正确
HTTP 200应用返回成功状态内容一定符合预期
业务数据正确整条链路当前可用未来不会抖动

“能 ping 通但不能访问服务”并不矛盾;“端口能连但请求失败”也不矛盾。

3. 第三原则:同一环境测试

很多排障误判来自测试环境不一致。

你在宿主机测试
程序在容器里运行

你在公司网络测试
用户在家庭网络访问

你用命令行测试域名
程序使用内部 DNS 缓存

你访问公网入口
服务内部调用走私有网络

所以要明确:

问题为什么重要
请求从哪里发起路由、DNS、NAT、防火墙都可能不同
使用哪个域名/IP解析结果和入口层可能不同
经过哪些代理Header、超时、缓存、错误码可能被改变
使用什么协议版本HTTP/1.1、HTTP/2、HTTP/3 行为不同
手动测试和程序是否同环境否则证据不能直接替代

4. 常用证据工具怎么理解

这里不强调命令细节,而强调每类工具提供什么证据。

工具类型看到什么用途
DNS 查询工具域名解析记录、TTL、解析器结果判断域名是否解析正确
pingICMP 往返和丢包粗略看网络层可达性
traceroute/tracert路径上的部分跳点判断大致路径和中途异常
TCP 连接测试端口是否能建立连接判断服务入口是否可连
HTTP 客户端状态码、Header、阶段耗时看应用协议行为
netstat/ss本机连接状态看 LISTEN、ESTABLISHED、TIME_WAIT、CLOSE_WAIT
抓包工具实际包序列验证 SYN、ACK、重传、RST、TLS 握手
日志/指标/追踪系统内部行为定位应用、网关、上游耗时

工具不是越多越好。每次只问:我现在需要证明哪一个假设?

5. 超时要分类

“timeout”不是一种原因,而是一类结果。常见超时:

超时类型含义方向
DNS timeout等不到解析结果DNS 服务器、网络、配置
connect timeoutTCP 握手没完成路由、防火墙、目标不可达、SYN 丢失
TLS handshake timeout安全通道没建立证书协商、协议、网络、中间设备
read timeout连接已建立但读不到响应服务处理慢、响应丢失、上游慢
write timeout数据写不出去或对端不读发送阻塞、接收方慢、连接异常
idle timeout空闲连接被关闭NAT、代理、网关、连接池策略
request timeout整体请求超过上限可能包含多个阶段

排障时要把整体超时拆成阶段耗时。否则会把服务处理慢误判成网络不通,或把握手失败误判成应用错误。

6. 错误现象映射表

现象常见方向
域名不存在DNS 记录、拼写、区域配置
解析到错误 IP缓存、TTL、CNAME、不同解析器
Connection refused目标端口无监听、服务未启动、策略拒绝
connect timeout路由、防火墙、目标不可达、SYN 被丢
reset by peer对端主动 RST、协议不匹配、连接被中间设备关闭
broken pipe本端继续写已关闭连接
400请求格式、参数、Header 错
401/403认证或权限问题
404路由、路径、资源不存在
429限流
502代理到上游异常
503无可用实例、过载、维护
504网关等上游超时
响应旧内容HTTP/CDN/浏览器缓存
偶发慢丢包、重试、队列、连接池、上游抖动

这张表只给初始方向,不能替代证据。下一步必须验证。

7. 抓包时看什么

抓包的价值是看到真实网络事件,而不是应用加工后的错误。

7.1 TCP 建连

正常三次握手:

SYN ->
<- SYN, ACK
ACK ->

如果只有:

SYN ->
SYN ->
SYN ->

说明 SYN 没得到有效响应,方向可能是目标不可达、防火墙丢弃、中间路径问题。

如果看到:

SYN ->
<- RST

常见含义是目标端口拒绝连接。

7.2 数据传输

关注:

是否有大量 Retransmission
ACK 是否正常增长
窗口是否很小
是否出现 Zero Window
是否有 RST

这些能帮助区分:

网络丢包
接收方读慢
对端主动断开
中间设备异常

7.3 TLS 和 HTTP

如果 TLS 握手前就失败,应用层 HTTP 不会出现。

如果 TLS 成功后 HTTP 返回 5xx,说明请求至少已经进入应用协议链路。

抓包时要尊重边界:

TLS 加密后,抓包能看到连接和握手元数据;
HTTP 明文内容通常看不到,除非在终止 TLS 的节点观察。

8. 慢请求分析:延迟、吞吐、丢包、排队

慢不一定是带宽不足。

概念含义常见表现
延迟单次往返需要多久首次响应慢、交互慢
吞吐单位时间传多少数据下载/上传慢
丢包包没有到达重传、窗口下降、抖动
抖动延迟波动大实时体验不稳定
排队中间设备或应用排队延迟突然升高
队头阻塞前面缺口阻塞后续交付某些流量被拖住

慢请求拆解:

DNS time
connect time
TLS time
request send time
server processing time
time to first byte
content download time

如果首字节之前慢,优先看连接、握手、服务处理、上游依赖。
如果首字节之后慢,优先看响应体大小、吞吐、丢包、窗口、客户端读取速度。

小实验:做一张最小请求瀑布表

选一个你能稳定访问的 HTTPS 地址,不急着抓包,先把一次请求拆成阶段记录:

阶段你要记录什么异常时的第一方向
DNS解析结果、TTL、解析耗时DNS 配置、递归解析器、缓存
TCPconnect 是否成功、耗时路由、防火墙、端口监听、SYN 丢失
TLS握手是否成功、证书信息证书链、SNI、协议版本、套件
HTTP send请求头/请求体是否发出客户端阻塞、代理限制、连接异常
First byte首字节等待多久服务排队、上游依赖、网关等待
Download响应体下载多久带宽、丢包、窗口、客户端读取慢

做完这张表后,再写一句结论,要求禁止使用“网络慢”这种笼统词。合格结论应该像:

DNS/TCP/TLS 都在正常范围内,首字节等待从 80ms 升到 2.4s,优先查网关到上游服务的排队和应用处理耗时。

这个练习的价值是把 vague symptom 变成 phase-specific evidence。能做到这一步,排障已经比“猜一个原因试一下”稳很多。

反例:本机命令成功,不代表真实运行环境成功

排障时常有人说:

我在本机 curl 成功,所以网络没问题。

这个结论经常跳太远。一次请求是否成功,取决于发起环境:

差异可能影响
DNS 配置不同解析到不同地址
出口 IP 不同被目标白名单、限流或风控区别对待
代理配置不同本机直连,运行环境走代理或网关
证书信任库不同本机信任,运行环境不信任
协议版本不同本机支持新 TLS/HTTP 版本,运行环境不支持
网络路径不同本机可达,运行环境所在子网不可达
超时设置不同命令默认等待更久,程序更早超时
请求头不同目标按 Host、SNI、User-Agent、鉴权头路由

正确做法是让证据尽量贴近真实发起点:

在同一机器上测
在同一网络隔离环境里测
使用同一域名、端口、协议、SNI、Host、请求头
使用接近真实程序的超时和代理配置
对比 DNS/TCP/TLS/HTTP 每阶段结果

本机测试只能证明“本机这条路径成功”。它是有用证据,但不能替代真实运行环境的证据。

9. 建立排障记录

严肃排障要留下记录。否则多人协作时会反复问同样问题。

一份最小记录:

时间:
发起方:
目标域名/IP/端口:
协议:
错误信息:
是否可复现:
DNS 结果:
TCP 连接结果:
TLS 结果:
HTTP 状态码:
请求耗时分解:
相关日志:
已排除项:
下一步假设:

这不是形式主义。它能防止排障在“猜一个、试一下、忘了刚才试过什么”里打转。

10. 三个实际排障模板

10.1 访问不了某个域名

  1. 域名能否解析?
  2. 解析到哪个 IP?
  3. IP 是否符合预期?
  4. TCP 目标端口能否连接?
  5. TLS 是否握手成功?
  6. HTTP 是否有状态码?
  7. 错误是否只在某个网络环境出现?

10.2 偶发 504

  1. 504 由哪一层返回:CDN、网关、代理?
  2. 请求是否到达应用?
  3. 应用处理时间是否超过网关超时?
  4. 下游依赖是否慢?
  5. 是否有重试放大流量?
  6. 连接池是否耗尽?
  7. 超时配置是否层层递减且合理?

证据链模板:504 要先证明是哪一层等超时

504 的字面意思通常是“某个网关等待上游超时”,但关键是:

哪个网关?
等待哪个上游?
请求是否已经进入真正处理逻辑?

最小证据链可以这样写:

客户端:
status = 504
total = 31s
connect = 20ms
tls = 40ms
first_byte = 31s

入口层:
有请求记录
upstream_time = 30s
upstream_status = timeout

处理层:
是否存在同一 request id
如果存在,处理到哪一步
如果不存在,问题在入口到处理层之间

依赖层:
同时间段是否有连接池等待、队列堆积、慢调用

根据证据,504 至少可以分成几类:

证据形态更可能的方向
客户端 connect/TLS 已快,TTFB 接近网关超时中间层等待上游
入口层没有请求记录请求没到入口,查 CDN/代理/路由
入口层有记录,处理层无记录转发、负载均衡、连接池或队列
处理层有记录且耗时接近超时处理逻辑或下游依赖慢
处理层很快完成,但入口仍 504响应路径、连接复用、网关状态异常

看到 504 不要直接说“处理慢”。先找返回 504 的那一层,再证明它在等谁。

10.3 长连接空闲后第一次请求失败

  1. 中间 NAT/代理是否有 idle timeout?
  2. 客户端连接池是否复用了已被关闭的连接?
  3. 服务端是否主动回收空闲连接?
  4. 是否需要心跳或更短的空闲回收?
  5. 失败后重试是否安全?

这些模板的共同点是:先定位阶段,再验证机制。

11. 联系实际:从“网络慢”到可执行结论

假设有人说“今天系统很慢”。一个可执行的拆解方式是:

  1. 慢的是所有用户,还是某些地区/网络?
  2. 慢的是所有接口,还是某些路径?
  3. DNS、TCP、TLS、首字节、下载哪段变慢?
  4. 是否出现 5xx、重传、丢包、连接池耗尽?
  5. 入口层、应用层、下游依赖指标是否同时变化?
  6. 最近是否有 DNS、证书、网关、发布、缓存策略变更?

最后的结论应该长这样:

不是“网络慢”四个字,
而是“某地区用户解析到某 CDN 节点后,首字节等待升高;源站日志显示上游处理正常,CDN 回源连接耗时异常,已切换该区域调度并观察”。

结论越具体,下一步动作越清楚。

失败指纹表:网络症状到协议阶段

现象首先定位的阶段关键证据常见下一步
域名偶尔解析到不同地址DNS 解析和缓存解析结果、TTL、递归解析器、权威记录对比不同网络/解析器,确认是否为缓存或调度策略
连接超时TCP 建连或路径可达SYN 重传、路由、丢包、防火墙记录区分目标不可达、端口被拦、回程路径异常
TLS 失败证书、SNI、协议版本、信任链证书链、域名匹配、有效期、TLS alert区分证书配置、客户端策略和中间层终止
首字节时间长服务处理或上游排队TTFB、服务 trace、upstream 日志、队列长度查源站、网关、负载均衡和应用处理
下载慢但 TTFB 正常传输吞吐、拥塞、窗口、客户端接收throughput、重传、RTT、TCP window查链路质量、拥塞控制、接收端消费速度
只某些地区慢路由、CDN、DNS 调度、运营商路径分地区 traceroute、CDN 命中、解析结果区分源站慢和边缘/路径慢

12. 学完本章你能解决什么问题

学完本章,你应该能:

  1. 把一次网络请求拆成 DNS、路由、TCP、TLS、HTTP、应用处理、连接关闭等阶段。
  2. 区分可达、可连接、握手成功、HTTP 成功、业务正确这些不同层次。
  3. 根据 timeout、refused、reset、502、503、504 等现象定位初始方向。
  4. 选择合适证据工具,而不是盲目堆命令。
  5. 用抓包判断 SYN、ACK、重传、RST、窗口等关键事件。
  6. 分析慢请求是延迟、吞吐、丢包、排队、缓存还是上游依赖问题。
  7. 写出可协作的排障记录,把“网络问题”变成可验证、可推进的技术问题。

延伸阅读