网页慢转圈排查:从物理层到应用层的分层诊断
一句话结论(30s)
网页慢排查要「先定位慢在哪、再分层排查」——因为先看 TTFB 和 Content Download 能快速锁定是后端/网络慢还是响应体太大,再按物理层→DNS→TCP→HTTP→应用层自下而上排除,用最小代价排除最多可能性(先近后远、先快后慢)。
核心原理(2min)
- 第零层定位:Network 面板看 TTFB(后端/网络慢)vs Content Download(响应体大/带宽不足)。
- 分层排查:物理层(网线/协商速率/丢包)→ DNS(解析耗时,换 114/8.8.8.8 对比)→ TCP/TLS 握手(RTT,用 curl 分段计时)→ HTTP(响应码/响应时间/体大小)→ 应用层(慢 SQL/缓存未命中/GC 暂停/线程池满)。
- 终极武器:
tcpdump/Wireshark 抓包看 TCP 重传、Zero Window(流控)、Dup ACK(乱序)、TLS Alert。
底层深入(5-10min)
用户反馈”网页打开很慢,一直在转圈”——这可能是最模糊也最让人头疼的问题描述。慢在哪里?网络?DNS?服务端?数据库?前端渲染?但如果你掌握了分层排查方法论,从底层到上层逐层排除,问题定位就会变得清晰可控。
第零层:先定位”慢在哪里”
打开浏览器开发者工具的Network面板,关注两个关键时间指标:
- TTFB(Time To First Byte):从发起请求到收到第一个字节的时间。TTFB长说明后端或网络慢。
- Content Download:从第一个字节到完整下载的时间。这个时间长说明响应体太大或者带宽不足。
如果TTFB长,走下面的分层排查流程;如果Content Download长,优先检查响应体大小(是否忘了分页、是否返回了大量不必要的数据)。
思考:为什么第一步是区分 TTFB 和 Content Download?因为这两个时间戳把「慢」一刀切成两半——TTFB 长说明「等响应等太久」(后端处理慢或网络慢),Content Download 长说明「下载花了太久」(响应体大或带宽不足)。不先定位慢在哪一段,就可能在错误的层上瞎查半天。
第一层:物理层——真的插了网线吗
这层听起来可笑,但现实中不在少数:Wi-Fi信号弱、网线松动、交换机端口坏。快速检查:
# 检查链路状态
ethtool eth0 # 查看协商速率,是否1000Mb/s还是降到了10Mb/s
ifconfig eth0 # 查看有没有大量error/drop包
cat /proc/net/dev # 看网卡统计,errors和dropped是否持续增长
# ping看丢包率和延迟抖动
ping -c 100 target_ip # 丢包率>1%就值得关注,延迟抖动大可能是链路不稳定
第二层:DNS解析——最容易被忽略的瓶颈
DNS解析是浏览器发出第一个HTTP请求之前必须完成的工作。如果DNS慢,用户看到的就是浏览器状态栏一直显示”正在解析主机…”。
# 检查DNS解析耗时
dig www.example.com # 关注Query time字段
time nslookup www.example.com # 简单测时
# 在Linux下用curl可以单独看DNS耗时
curl -w "dns: %{time_namelookup}s\n" -o /dev/null -s https://example.com
常见DNS慢的原因:DNS服务器响应慢(换114DNS或8.8.8.8对比测试)、DNS缓存未命中、域名有大量CNAME链(每次跳转都要解析)。
第三层:TCP握手——建立连接的隐形开销
HTTPS请求在传输应用数据之前要经历:
- DNS解析(UDP往返,通常<50ms)
- TCP三次握手(1个RTT)
- TLS握手(HTTPS特有,2个RTT,TLS 1.3优化到1个RTT)
如果用户和服务器之间RTT=200ms,光是建立连接就要花600ms(DNS+TLS 1.2),这还没开始传数据。
思考:为什么高延迟场景下「握手」也会成为隐形杀手?因为 HTTPS 建连要叠加 DNS + TCP 三次握手 + TLS 握手,每一步都是一次往返。RTT 200ms 时,光建连就要 600ms,还没开始传数据。这解释了为什么「就近部署/CDN/连接复用」对远距离用户如此重要——省的不是传输,是往返次数。
# 用curl分段测量
curl -w "tcp: %{time_connect}s\ntls: %{time_appconnect}s\n" -o /dev/null -s https://example.com
# tcptraceroute 看每一跳的延迟
tcptraceroute example.com 443
第四层:HTTP层——服务端到底在干什么
到了HTTP层,关注三个数字:
- 响应码:200正常;3xx看是不是做了不必要的重定向;4xx/5xx就是直接报错了。
- 响应时间:服务端处理逻辑慢(慢SQL、外部API调用超时、大量计算)。
- 响应体大小:是否返回了大量无用数据。
服务端排查:
# 直接对后端做基准测试,排除网络因素
curl -w "total: %{time_total}s\n" -o /dev/null -s http://localhost:8080/api/test
# 用strace看系统调用耗时(排查IO瓶颈)
strace -T -p $PID 2>&1 | grep -E 'read|write|poll'
第五层:应用层——代码和数据库
进入应用层后,常见瓶颈:
- 慢SQL:用
SHOW PROCESSLIST看慢查询,EXPLAIN分析执行计划,检查是否缺少索引。 - 缓存未命中:Redis是否正常工作,缓存命中率是否正常。
- GC暂停:JVM是否在Full GC(
jstat -gcutil $PID 1000),Go是否在做STW标记。 - 线程池满:所有工作线程都在处理慢请求,新请求排队等待。
# 查看JVM GC情况
jstat -gcutil $PID 1000 10
# 查看线程状态
jstack $PID | grep -A 10 "BLOCKED\|WAITING"
终极武器:抓包分析
如果分层排查都找不到问题,上抓包(tcpdump/Wireshark):
tcpdump -i eth0 -w capture.pcap port 80 or port 443
用Wireshark打开后重点看:
- TCP重传(Retransmission)数量——多说明丢包严重
- TCP Zero Window——接收方处理不过来了,在流控
- TCP Dup ACK——乱序到达
- TLS Alert——加密层出问题了
思考:抓包里的 Zero Window 和 Dup ACK 分别暴露了什么?Zero Window 是接收方通告「我窗口为 0、处理不过来了」,说明接收端在流控、应用消费跟不上;大量 Dup ACK 说明乱序或丢包,接收方在反复催同一个包。抓包的价值就在于把「慢」还原成这些可读的信号,而不是靠猜。
排查思维总结
记住一句话:先近后远,先快后慢。先排除最简单的(插网线、DNS),再逐步深入到复杂的(数据库死锁、GC问题)。每次排查前先问自己”这个检查能在2分钟内完成吗”,可以的话立刻做——分层排查法的本质就是用最小代价排除最多可能性。
章末提问
Q1:网页加载很慢,你的排查思路是什么?
结论先行:先定位慢在哪一段(TTFB vs Content Download),再自下而上分层排查(物理→DNS→TCP/TLS→HTTP→应用)。因为先看时间戳能立刻锁定是「后端/网络慢」还是「响应体大」,再用分层法从最便宜到最贵逐层排除,符合「先近后远、先快后慢」的最小代价原则。
Q2:TTFB 长和 Content Download 长分别代表什么?
结论先行:TTFB 长说明后端处理慢或网络慢,Content Download 长说明响应体太大或带宽不足。因为 TTFB 是从发请求到收到第一个字节的时间,反映「服务端多久开始响应」;Content Download 是从第一个字节到下载完成的时间,反映「数据量/带宽」,两者排查方向截然不同。
Q3:抓包看到大量 TCP 重传和 Zero Window 分别说明什么?
结论先行:大量重传说明链路丢包严重,Zero Window 说明接收方处理不过来在流控。因为重传是「包丢了要重发」的信号,通常意味着网络质量差或拥塞;Zero Window 是接收方通告窗口为 0,说明应用消费跟不上、接收缓冲区满了,问题在接收端处理能力而非网络。