3042 字
约 10 分钟
22
S02-A05 · 网络排障分层:从现象定位到层

"网站慢"这句话在三个群里会得到三个答案。运维说机器 CPU 12%、带宽没打满,不是他的问题;开发说本地跑同一个接口几十毫秒,不是代码问题;用户说就是打不开。三方都没说谎,因为他们看的是不同的层。排障的第一步不是查,是把现象归到层上——层判断错了,后面每条命令都在给错误假设找证据,越查越像有道理。

决策视角只有三件事:哪类现象先怀疑哪一层、每层的最小验证动作是什么、什么时候该停止网络排查。


1. 先分类现象,再谈分层

"慢"和"打不开"必须拆成可验证的五类。分类只问三个问题:是不是所有人都受影响、是不是所有请求都受影响、出错发生在拿到第一个字节之前还是之后。

现象 典型表现 优先怀疑 经验分布(判断用,不是实测)
连不上 超时、Connection refused、reset L3/L4:路由、安全组、端口 连接层多数,DNS 次之,应用最少
连上很慢 TCP 建了,首字节迟迟不来 L7:应用排队、上游依赖 应用为主,TLS 与 TCP 各占小头
时快时慢 p50 正常、p99 爆掉 资源池、GC、回源、限流 池与 GC 为主,链路为辅
部分用户不行 同一 URL 有人好有人坏 DNS、运营商、地域 DNS 与运营商为主
特定请求不行 只有某接口、某参数、某文件 应用、网关规则、大小限制 几乎全在应用与网关

分类的价值在排除:一旦确认所有请求、所有用户都慢,DNS 与客户端版本可以直接划掉。


2. 分层定位的最小动作集

五个探针按顺序打,每段只回答一个问题,段与段之间做减法。不要一上来就抓包——抓包回答不了"慢在哪一段"。

$ curl -o /dev/null -s \
  -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
  https://TARGET/health
dns=0.004 tcp=0.031 tls=0.089 ttfb=0.412 total=0.418
段 减法 这一段慢说明什么 下一步
DNS time_namelookup 解析器远、递归慢、权威超时 dig 对比本地与公共解析
TCP connect - namelookup 路由绕、SYN 排队、backlog 满 mtr、看 ListenOverflows
TLS appconnect - connect 证书链拉取、OCSP、无会话复用 openssl s_client -status
首字节 starttransfer - appconnect 服务端处理、排队、下游依赖 换应用侧线程栈/慢日志
内容 total - starttransfer 传输窗口、压缩、分块、客户端读得慢 看响应体大小与 Content-Encoding

纪律:单次 curl 只当探针,不当结论。至少跑 20 次看分位,别把一次冷启动的 DNS 当常态。


3. "能 ping 通但打不开"说明了什么

它只说明一件事:ICMP 到那台机器的路径通。ICMP 和 TCP 443 走的不是同一条策略链,中间设备对二者的处理经常完全不同。

现象组合 更可能的层 判定动作
ping 通、curl 超时 端口没监听或被安全组挡 ss -lntp 在本机看监听,从外侧 nc -vz
ping 通、立刻 refused 进程没起或绑了 127.0.0.1 ss -lntp 看绑定地址
ping 通、TLS 阶段失败 证书/SNI/中间设备拦截 openssl s_client -servername TARGET
ping 通、返回 403/421 网关按 Host 头或 SNI 分流 带 -H 'Host: ...' 复测
ping 通、只有大响应卡住 MTU/分片、窗口、代理缓冲 小文件对照 + ping -M do -s 1472

反过来 ping 不通而页面正常也常见:ICMP 被丢弃、TCP 放行。用 ICMP 判断可用性从一开始就是错的探针。


4. 延迟高和丢包是两件不同的事

两者都表现为慢,修复手段互不通用:RTT 高要改路径,丢包要改队列与链路。混着查只会得出"扩容"这类无效结论。

信号 含义 常见误判
RTT 整体抬高、方差小 路径变长(绕路、跨地域、代理多一跳) 误判为"带宽不够"
RTT 稳定但重传率高 链路质量差、拥塞丢包 误判为"服务端慢"
RTT 抖动大、重传随之上行 队列积压(bufferbloat) 误判为"对端处理不过来"
只有尾包重传 中间设备限速或 MTU 黑洞 误判为"应用写响应慢"
建连耗时高于传输耗时 握手阶段问题,与带宽无关 误判为"要加机器"
$ nstat -az TcpRetransSegs TcpExtTCPTimeouts TcpExtListenOverflows TcpExtTCPLostRetransmit
$ ss -s | head -5          # 全局 socket 与重传概况
$ mtr -rwzc 100 TARGET     # 逐跳丢包:末跳丢 vs 中间跳丢

判据:逐跳丢包只有末跳丢才算真丢,中间跳丢包往往是路由器对 ICMP/UDP 探测限速。mtr 的中间跳 20% 丢包而末跳 0%,说明链路是好的。


5. 时快时慢的四个来源

p99 爆炸而 p50 正常,几乎不可能是网络设备——设备故障会让所有请求一起慢。四个来源有各自的指纹:

来源 指纹 排除动作
连接池耗尽 慢请求成批出现,间隔约等于获取超时;等待线程堆积 打池指标:活跃/等待/获取耗时
GC 停顿 慢请求呈秒级块状,与堆曲线同步 对照 GC 日志时间戳,看是否同一秒
CDN 回源 只在缓存未命中或过期后出现,源站 QPS 尖刺 看回源率与缓存命中率,X-Cache 头
上游限流 慢与 429/503 同时出现,集中在某一依赖 看依赖侧限流计数与重试次数

四个来源的共同点是排队,区别是排在哪。先看是否所有实例同时慢(是 → 共享依赖;否 → 单实例资源),再对齐 GC 或缓存过期的时间点。


6. 部分用户不行:归因顺序不能乱

顺序错了会白跑:先查客户端版本,会漏掉整片地域。

  1. 地域:同一 URL 从两个地域探活,差异稳定即为地域问题;
  2. 运营商:同地域换出口线路,差异稳定即为线路问题;
  3. DNS 解析差异:不同解析器返回不同 IP,落到不同源站或过期记录;
  4. 客户端版本:最后才查,因为它只解释"个体差异",解释不了"整片失败"。
$ dig +short TARGET A @LOCAL_RESOLVER
$ dig +short TARGET A @8.8.8.8
$ dig +trace TARGET | tail -20        # 看权威是谁、委派断在哪

第 3 步最常见的坑是解析正确但缓存了旧 IP:TTL 过长,切换后仍有大量用户打到旧地址,表现为"失败比例随时间下降",常被误判成服务端不稳。


7. 代理与网关链路:找到最少可复现的一跳

链路越长越要切开:客户端 → 边缘 → 网关 → 应用。方法只有一句:从离故障最近的一跳开始向两端扩张,直到第一个能稳定复现的跳。

# 同一路径、同一 Host,只改连接目标
$ curl -s -o /dev/null -w 'edge=%{time_starttransfer}\n' https://EDGE_HOST/health -H 'Host: TARGET'
$ curl -s -o /dev/null -w 'origin=%{time_starttransfer}\n' http://ORIGIN_IP:PORT/health -H 'Host: TARGET'

两边都要带相同的 Host 与路径,差异才可信。反向代理场景还要核对三处:转发头是否被覆盖、超时是否逐层放大(网关 60s、代理 30s、应用 5s,用户等到的是 60s)、保活复用是否被中间层打断。


8. 观测盲区:看不到不等于没问题

盲区 为什么看不见 替代手段
NAT/SNAT 端口耗尽 应用侧只看到"连不上对端" 看 NAT 网关的转换表与失败计数
负载均衡健康检查 检查通过但真实请求失败(路径不同、Host 不同) 用真实请求复测检查路径
云厂商内网与安全组 主机内抓包看不到被丢弃的包 用 VPC 流日志 / 安全组拒绝计数
容器网络 抓的是容器 veth,看不到节点侧丢包 节点侧抓 cni0/eth0,对照两侧计数
TLS 中间设备 应用日志一切正常,握手却慢 对比两侧握手耗时与证书链长度

处理原则:先补观测,再谈归因。缺观测时靠猜,猜错还会留下"已验证"的错误结论。


9. 证据链:抓包与时间戳对齐

$ date -u +%Y-%m-%dT%H:%M:%S.%3N       # 记录本机时间基准
$ tcpdump -i eth0 -nn -s0 -w cap.pcap 'host PEER_IP and port 443'
$ tshark -r cap.pcap -q -z io,stat,1 -z expert
$ tshark -r cap.pcap -Y 'tcp.analysis.retransmission' | wc -l

三件必须同时保存:抓包文件、两端时间基准、请求标识(trace id 或 URL+时间)。只有抓包无法与应用日志对齐;只有日志无法证明包发出去了没回。


10. 排错:五种典型误判

现象 真实原因 处理
curl 首字节 400ms,应用日志显示 5ms 慢在等排队/等连接获取 看池等待指标,不是看业务耗时
只有部分实例慢 单实例资源或该实例到依赖的链路 按实例维度切分指标,别用全局均值
加带宽后没变化 瓶颈在握手或应用排队 回到分段计时,确认段再说优化
抓包里大量重传但用户无感 重传被快速恢复,未触及超时 以尾延迟为准,别以计数为准
换 DNS 后短暂更糟 TTL 未过期、解析结果混用 缩短 TTL、灰度切换、观察收敛时间

11. 边界:什么时候别做网络排查

场景 该做什么 理由
单机本地进程间调用出问题 直接看进程与日志 没有链路可分层,分层只是仪式
已确认是应用逻辑错误 修逻辑 网络排查只会延后修复时间
没有链路观测、也没有分段计时 先补观测 无数据的归因等于猜
慢只出现在压测工具侧 查压测机自身 工具端资源与连接数常是瓶颈
协议层一切正常但业务结果错 查数据与逻辑 传输正确不等于语义正确

一条判据收尾:先分层、再分段、后抓包。分层为了少查,分段为了知道该抓哪段,抓包留最后是因为它最贵。


12. 自测

  1. 用户说"网站慢",你要先问哪三个问题才能把它归到五类中的一类?
  2. time_connect 与 time_namelookup 的差值变大,最可能是什么环节?
  3. 能 ping 通但 HTTPS 打不开,为什么不能据此排除网络问题?
  4. 逐跳 mtr 里中间跳丢包 20%、末跳 0%,结论是什么?
  5. p50 正常而 p99 突增,为什么优先怀疑连接池而不是网络设备?
  6. 只保留抓包文件、不保存两端时间基准,事后会失去什么能力?
S02-A05 · 网络排障分层:从现象定位到层
https://www.clxhxhhr.top/posts/6164/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。