上一篇 下一篇 分享链接 返回 返回顶部

网站打开速度慢如何从DNS、服务器到网页逐层排查瓶颈

发布人:Minchunlin 发布时间:2026-10-06 14:45 阅读量:4

网站打开速度慢,不能仅凭“服务器响应慢”下结论。一次完整的页面访问通常要经过 DNS 解析、建立 TCP 连接、TLS 握手、Web 入口处理、应用执行、数据库查询、响应传输以及浏览器解析渲染。应先观察慢发生在哪一个阶段,再判断责任范围:DNS 时间高,优先看域名解析;连接和握手时间高,优先看网络、IP 地址或入口服务;首字节等待时间高,重点检查应用和数据库;首字节正常但页面仍迟迟可用,则要转向响应体大小、静态资源和前端渲染。

还要区分“所有访问都慢”“某个地区慢”“首次打开慢”“只有特定接口慢”以及“页面看似打开但交互很慢”。这些现象对应的原因树并不相同。下面按由外到内、由低风险到高风险的顺序排查,示例命令、日志和指标均用于说明判断方法,不代表已经在某个具体环境中执行过。

先确认慢的具体症状

统一测试条件

排查前先固定几个变量,否则不同时间、不同网络和不同页面之间的结果无法直接比较。

建议记录以下信息:

  • 访问的完整 URL、HTTP 方法和是否需要登录。
  • 测试时间、所在地区、运营商或出口网络。
  • 首次访问与连续刷新后的结果。
  • 使用 IPv4 还是 IPv6。
  • 是否经过 CDN、负载均衡、WAF 或反向代理。
  • 慢的是首页、静态资源,还是某个接口。
  • 浏览器中是否出现 4xx、5xx、超时或资源加载失败。

同一个页面至少进行三次轻量测试,并保留每次的分阶段耗时。不要在故障期间反复刷新动态接口,以免把排查行为变成额外负载。

在 Linux、macOS 或安装了 curl 的环境中,可以使用下面的只读请求观察基础耗时:

curl -sS -o /dev/null \
  -w 'http_code=%{http_code}\nremote_ip=%{remote_ip}\nnamelookup=%{time_namelookup}s\nconnect=%{time_connect}s\nappconnect=%{time_appconnect}s\npretransfer=%{time_pretransfer}s\nstarttransfer=%{time_starttransfer}s\ntotal=%{time_total}s\nsize_download=%{size_download}B\n' \
  --connect-timeout 10 \
  --max-time 30 \
  'https://www.example.com/'

这些字段可以这样理解:

字段主要反映常见判断方向
namelookupDNS 解析耗时域名服务器、递归解析器、A/AAAA 记录
connectTCP 建连完成时间网络往返、端口可达性、入口服务连接队列
appconnectTLS 握手完成时间证书链、加密协商、网络抖动、TLS 终止设备
starttransfer收到首字节的时间连接建立后等待 Web 服务、应用、数据库返回
total整个响应完成时间首字节等待加下载和传输时间
size_download实际下载字节数HTML、接口响应或静态文件体积

例如,namelookup=0.02s、connect=0.05s、starttransfer=2.80s,通常不是 DNS 或 TCP 建连慢,而是 Web 入口等待后端处理。若 starttransfer=0.15s,但 total=8.00s,则要重点检查响应体大小、带宽、丢包、压缩以及浏览器后续资源。

curl 的一次结果不能代表所有用户。还应使用浏览器开发者工具的 Network 面板观察请求瀑布图,关注请求排队、DNS、Initial connection、SSL、Waiting for server response、Content Download 等阶段。浏览器显示的页面可用时间还会受到 JavaScript 执行、字体加载、图片解码和第三方资源影响,因此它可能明显晚于 HTML 请求完成时间。

区分首次访问和重复访问

首次打开慢、刷新后明显变快,常见原因包括:

  • DNS、TLS 或浏览器连接尚未复用。
  • CDN 或应用缓存首次未命中。
  • PHP、Java、Node.js 等应用进程刚启动。
  • 数据库缓存、文件系统缓存尚未热起来。
  • 浏览器首次下载了字体、脚本和图片。

如果连续访问都慢,才更应该关注持续性的网络、服务器、应用或数据库问题。测试时应分别记录“冷访问”和“热访问”,不要把两种结果混为一个平均值。

先看影响范围

影响范围是建立原因树的重要线索。

现象范围优先怀疑方向下一步
所有域名和接口都慢主机资源、出口网络、入口服务检查系统负载、连接数和链路
只有一个域名慢DNS、虚拟主机配置、该站点应用比较解析结果和站点日志
只有一个地区或运营商慢DNS 调度、路由、某个边缘节点从多地区测试 A/AAAA、连接和 TTFB
只有首次访问慢DNS、TLS、缓存、冷启动对比首次和重复访问
只有动态接口慢应用、数据库、外部依赖看接口级日志和上游等待
静态文件慢,接口正常文件体积、CDN、网络传输看缓存命中、压缩和下载阶段
网络请求很快但页面迟迟可用JavaScript、渲染、第三方资源看 Performance 和长任务

建立“网站变慢”的原因树

可以把一次请求拆成五层:

建立“网站变慢”的原因树配图

  1. 名称解析层:域名是否快速、稳定地解析到正确地址。
  2. 链路与接入层:客户端到 CDN、负载均衡或服务器的连接是否稳定。
  3. Web 入口层:Nginx、Apache、网关或负载均衡是否在排队。
  4. 应用与数据库层:业务代码、缓存、数据库和外部依赖是否耗时。
  5. 资源与浏览器层:响应体、图片、脚本和页面渲染是否拖慢可用时间。

排查时不要在每层都直接改配置。先通过耗时拆分、日志和相关指标确定分支,再做单项验证。一个适合快速定位的判断顺序如下:

  • DNS 时间高:先查解析,不要先重启服务器。
  • TCP 或 TLS 时间高:先查链路、IPv4/IPv6、入口 IP 和连接队列。
  • TTFB 高而下载短:先查 Web 入口、应用、缓存和数据库。
  • TTFB 正常而下载长:先查响应大小、压缩、带宽和丢包。
  • 网络请求完成但页面慢:先查前端脚本、图片、字体和第三方调用。

第一层:排查 DNS 解析

DNS 慢不等于服务器慢

DNS 解析通常会被递归解析器、操作系统或浏览器缓存。解析慢可能只影响首次访问,但如果权威 DNS 响应超时、记录配置不完整或某个解析地址不可达,用户仍可能频繁遇到等待。

可以先查询域名的基本记录:

dig www.example.com A
dig www.example.com AAAA
dig www.example.com CNAME

关注以下内容:

  • 是否存在意外的 CNAME 多级跳转。
  • A 记录和 AAAA 记录是否都指向可用入口。
  • 返回了多少个 IP,是否存在某一个异常地址。
  • Query time 是否明显高于其他时间。
  • TTL 是否过短,导致递归解析器频繁回源。
  • 是否出现 SERVFAIL、REFUSED 或超时。

下面是格式示例,数值仅用于演示:

;; ANSWER SECTION:
www.example.com.  300  IN  A  203.0.113.20

;; Query time: 18 msec
;; SERVER: 192.0.2.53#53

一次查询耗时 18 毫秒并不能证明所有用户都正常,也不能仅凭一次 800 毫秒的查询就判定权威 DNS 故障。应从不同网络、不同递归解析器重复观察,并对比本地 DNS 与权威 DNS 的结果。

重点检查 A、AAAA 和解析调度

如果域名同时配置 A 和 AAAA,而 IPv6 路径、IPv6 入口或防火墙配置不完整,部分客户端可能优先尝试 IPv6,等待失败后再回退 IPv4,表现为“有些用户打开很慢”。

第一层:排查 DNS 解析配图

可以分别比较两种协议:

curl -4 -sS -o /dev/null \
  -w 'IPv4 total=%{time_total}s connect=%{time_connect}s starttransfer=%{time_starttransfer}s\n' \
  --max-time 20 \
  'https://www.example.com/'

curl -6 -sS -o /dev/null \
  -w 'IPv6 total=%{time_total}s connect=%{time_connect}s starttransfer=%{time_starttransfer}s\n' \
  --max-time 20 \
  'https://www.example.com/'

如果 IPv4 稳定而 IPv6 经常超时,问题范围通常落在 IPv6 路径、AAAA 指向、监听地址或访问控制,而不是应用代码。是否调整 AAAA 记录,应先确认所有 IPv6 入口和回源链路,避免只改 DNS 隐藏真实故障。修改 DNS 前要记录原记录和 TTL,变更后根据 TTL 和递归缓存情况等待传播,并准备恢复原记录的回滚方案。

如果使用 CDN 或 DNS 调度服务,还应比较不同地区返回的 IP。某一地区持续返回异常地址,可能是调度策略、边缘节点健康检查或区域链路问题。此时不要直接把解析结果中的 IP 当作源站 IP,也不要绕过既有安全设备进行未经授权的回源测试。

第二层:排查网络、连接和 TLS

连接慢要拆成网络慢与入口排队

当 DNS 已经很快,但 connect 或 appconnect 明显升高,可能原因包括:

  • 客户端到入口 IP 的网络延迟或丢包。
  • 某个运营商到目标机房的路由异常。
  • IPv4 和 IPv6 路径质量差异。
  • TCP 连接队列、文件描述符或连接跟踪表接近上限。
  • TLS 握手协商、证书链或加密设备处理缓慢。
  • 防火墙、WAF、负载均衡器正在丢包或限流。

可以从客户端观察路径,但不能把中间路由器不响应 ICMP 直接视为网站丢包:

ping -c 20 www.example.com
mtr -rwzbc 20 www.example.com

ping 只能反映 ICMP 的响应情况,不等价于 HTTPS 请求结果。mtr 中某一跳显示丢包,而后续跳和最终目标正常,常常只是该中间设备限制了 ICMP。只有从某一跳开始,后续各跳和最终目标都持续出现相近比例的丢包,才更值得结合 TCP 或 HTTPS 测试继续判断。

如果条件允许,可以用 curl 直接重复请求同一个域名,并记录返回的 remote_ip。不同次请求命中不同 IP 时,应按 IP 汇总耗时,而不是只看总体平均值。对某个已知入口 IP 做验证时,优先使用 --resolve 保留域名和 TLS SNI:

curl --resolve www.example.com:443:203.0.113.20 \
  -sS -o /dev/null \
  -w 'ip=%{remote_ip} code=%{http_code} connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n' \
  --max-time 20 \
  'https://www.example.com/'

这里的 203.0.113.20 只是文档示例地址。实际测试只能使用已经确认属于本业务、且允许测试的入口 IP。不能随意把域名解析到陌生地址,也不能将直接访问源站的结果与经过 CDN 的结果混为一谈。

从服务器侧看连接状态

在 Linux 主机上,可以使用以下只读命令查看连接和网卡统计:

ss -s
ss -lnt
ip -s link

重点关注:

  • TCP 总连接数是否突然升高。
  • 监听端口是否存在大量 SYN-RECV,提示握手队列或攻击流量压力。
  • TIME-WAIT 数量是否异常,但不能仅凭数量判定故障。
  • 网卡是否出现明显丢包、错误或丢弃。
  • 监听服务是否只绑定了 IPv4 或只绑定了 IPv6。

若使用 systemd 管理服务,可查看服务状态和近期日志:

systemctl status nginx --no-pager
journalctl -u nginx --since "15 minutes ago" --no-pager

服务名可能是 apache2、httpd 或其他自定义名称,先用实际部署方式核对,不要直接套用命令。若发现端口监听正常但外部连接仍慢,应继续对比主机内网测试、入口设备日志和外部多地点测试。

第三层:排查 Web 入口和反向代理

用请求时间字段区分入口与上游

Nginx、Apache、网关或负载均衡器通常能记录请求总时长和上游耗时。以 Nginx 为例,常见的诊断字段包括:

  • $request_time:从接收请求到完成响应的总时间。
  • $upstream_connect_time:连接上游应用的时间。
  • $upstream_header_time:连接上游后等待上游响应头的时间。
  • $upstream_response_time:从连接上游到接收完上游响应的时间。

示例日志格式如下,字段布局仅作说明:

2025-03-08T10:20:31+08:00 request_time=2.418 upstream_connect_time=0.004 upstream_header_time=2.391 upstream_response_time=2.402 status=200 request="GET /api/orders HTTP/1.1"
2025-03-08T10:20:32+08:00 request_time=0.082 upstream_connect_time=- upstream_header_time=- upstream_response_time=- status=200 request="GET /assets/app.css HTTP/1.1"

第一行表示 Nginx 很快连上应用,但等待上游响应头接近 2.4 秒,优先检查应用和数据库。第二行没有上游字段,可能是静态文件由 Nginx 直接返回,耗时仅 82 毫秒。

如果 request_time 高,而 upstream_response_time 很低,可能是响应体传输慢、客户端读取慢、代理缓冲或网络链路问题。如果两者都高,则继续向应用层追踪。若大量请求返回 499,常见含义是客户端在服务端完成响应前主动断开,但仍需结合客户端超时设置和后端耗时判断,不能直接认定为服务器故障。

检查入口服务的排队和缓存

Web 入口层常见瓶颈包括:

  • worker 进程或线程不足。
  • 上游连接池耗尽。
  • keepalive、代理缓冲或超时配置不合适。
  • 静态文件未命中缓存,每次都回源。
  • CDN 缓存未命中,源站承受大量重复请求。
  • TLS 终止设备、WAF 或负载均衡器资源不足。
  • 某个接口突发流量拖慢了同一入口上的其他请求。

可以将同一 URL 分别测试缓存命中和未命中情况,观察响应头中的 Age、缓存状态、自定义上游标记以及 Cache-Control。不要只看 HTTP 状态码为 200 就认为请求健康,200 响应也可能等待了几秒。

如果要调整 Nginx、网关或负载均衡配置,应先备份当前配置,确认变更只影响目标站点或目标 upstream,使用配置校验命令后再平滑加载,并保留原配置作为回滚版本。例如 Nginx 配置变更前后应遵循:

sudo cp -a /etc/nginx /etc/nginx.backup-$(date +%Y%m%d%H%M%S)
sudo nginx -t

只有在 nginx -t 通过且确认影响范围后,才考虑按现有运维流程 reload。不要在没有备份、没有变更窗口或没有回滚路径时直接修改连接数、超时、缓存和 worker 参数。参数变大不一定更快,也可能把压力继续传给应用和数据库。

第四层:排查应用服务

用 TTFB 和接口维度定位代码等待

如果 DNS、TCP 和 TLS 都正常,而 starttransfer 较高,重点就从网络转向 Web 入口之后。应用慢的常见原因包括:

  • 某个 SQL 查询耗时增加。
  • 等待数据库连接池、线程池或任务队列。
  • 调用支付、消息、搜索等外部服务超时。
  • 缓存未命中或缓存服务响应慢。
  • 大量锁竞争、垃圾回收或单线程事件循环阻塞。
  • 近期发布引入了低效循环、重复查询或大对象序列化。
  • 某个接口被突发请求放大,拖慢共享进程。

不要只看整站平均 TTFB,应按路径、方法、状态码、版本和请求来源分组。例如首页可能只有 100 毫秒,而 /api/report 达到 4 秒;两者的排查方向完全不同。

建议为一次请求保留可关联的请求 ID,并在入口日志、应用日志和数据库调用日志中传递。一个完整的应用日志应至少能回答:

  • 请求进入应用的时间。
  • 排队等待了多久。
  • 业务代码执行了多久。
  • 数据库调用次数及总耗时。
  • 外部 HTTP/RPC 调用次数及耗时。
  • 序列化、模板渲染和响应写出的耗时。
  • 最终状态码和响应大小。

示例应用日志可以这样理解:

request_id=7f31 route=/api/report queue=0.012s db=2.184s external=0.006s render=0.031s total=2.247s status=200
request_id=8a42 route=/api/report queue=1.806s db=0.041s external=0.004s render=0.012s total=1.869s status=200

第一条更像数据库查询慢,第二条数据库本身很快,但请求在应用队列中等待,可能是线程池、进程数或并发控制出现瓶颈。只有 total 而没有分段数据时,不要直接猜测具体代码位置,应先补充观测。

关注超时和错误,不要只看成功请求

大量 200 并不代表没有性能问题。应用可能在接近超时前返回 200,用户仍然感觉页面迟缓。相反,少量 500 可能是慢查询、连接池耗尽或外部依赖超时的结果。

应同时查看:

  • 2xx、3xx、4xx、5xx 的比例变化。
  • 连接池使用率和等待时间。
  • 线程池、协程池或消息队列积压。
  • 外部依赖的超时、重试和熔断次数。
  • GC 暂停、事件循环延迟或进程重启。
  • 发布前后同一路由的 p50、p95、p99 延迟。

平均值容易掩盖尾部请求。假设 95% 请求在 200 毫秒内完成,但 5% 请求等待 8 秒,用户仍可能频繁遇到明显卡顿。排查时应优先看 p95 和 p99,并把慢请求样本与时间点对应到日志,而不是只看全天平均值。

第五层:排查数据库和缓存

数据库慢通常表现为 TTFB 高

当应用日志显示数据库调用占据大部分请求时间,应进一步区分查询执行慢、等待连接慢和锁等待慢。

常见表现如下:

观察结果更可能的原因继续检查
单条查询执行时间持续升高索引、扫描行数、数据量、执行计划慢查询日志和执行计划
查询本身很快,但应用等待连接连接池过小、连接未释放、数据库连接上限应用池等待和数据库连接数
某些时间段突然大量等待锁竞争、批处理、长事务活跃事务和锁等待
读请求变慢且磁盘繁忙缓存未命中、内存不足、随机 I/OBuffer 命中、磁盘延迟
只有报表或导出接口慢大范围扫描、排序、聚合查询范围、分页和异步化

生产环境查询诊断应使用只读账号和低影响方式。查看活动连接、慢查询统计通常风险较低,但仍可能增加监控开销;对复杂语句执行 EXPLAIN 前要确认数据库版本和语句类型,不能在生产环境随意执行会真正运行查询的分析命令。涉及索引、表结构、参数或事务设置的变更,应先备份或保留可恢复方案,在测试或低峰环境验证后再发布。

不要用“数据库 CPU 不高”排除数据库问题。锁等待、磁盘延迟、连接池等待和网络阻塞都可能在 CPU 较低时发生。还要检查应用是否存在 N+1 查询:一个页面请求先查询列表,再为每条记录分别查询详情,数据量增大后延迟会按记录数放大。

缓存命中不能替代数据一致性判断

缓存可能让首页很快,但动态接口仍然慢;也可能缓存失效后,大量请求同时回源,形成缓存击穿。应观察:

  • 缓存命中率和未命中率。
  • 缓存键是否包含不必要的用户或时间参数。
  • 未命中时的回源耗时。
  • 热点数据是否在同一时间集中失效。
  • 缓存服务连接数、内存和淘汰次数。
  • 数据更新后是否出现旧数据或缓存雪崩。

不要为了追求速度盲目延长所有缓存时间。缓存策略需要与数据时效、权限隔离和失效机制一起验证。若变更缓存规则,先记录原有 TTL、键规则和失效方式,确保出现数据错误时可以恢复。

第六层:排查服务器资源和系统限制

应用和数据库之外,主机本身可能受到 CPU、内存、磁盘、网络或系统限制。Linux 上可以先执行以下只读检查:

uptime
free -h
vmstat 1 5
df -h
df -i
ss -s

如果系统安装了 sysstat,还可以使用:

iostat -xz 1 5
pidstat -u -r -d 1 5

判断时不要只看单一指标:

  • CPU 使用率高:检查是 Web 进程、数据库、压缩、加密还是其他任务消耗。
  • CPU 使用率不高但 load average 高:可能存在磁盘 I/O 等待、不可中断睡眠或锁竞争。
  • 内存使用接近上限且 swap 活跃:应用可能因换页产生明显延迟。
  • 磁盘利用率高、await 增大:数据库、日志写入或文件读取可能被拖慢。
  • 磁盘空间或 inode 用尽:日志、临时文件和应用写入可能失败。
  • 网卡错误、丢弃增加:需要检查虚拟网卡、宿主机、带宽和上游设备。
  • 文件描述符接近上限:新连接、日志或文件读取可能失败。
  • 容器受到 CPU 或内存配额限制:宿主机空闲不代表容器有足够资源。

load average 是等待运行或等待资源的任务数量概览,不是 CPU 百分比。虚拟机中的 CPU steal、容器 cgroup 限制和宿主机 I/O 争用,也可能使应用延迟上升而主机总体指标看起来正常。

如果运行在容器中,应同时查看容器层面的 CPU、内存、重启次数和限制值。不要在故障期间直接提高容器配额或关闭 swap 来“试试效果”,这类改动可能扩大影响范围。先保留当前配置和监控数据,确认瓶颈后再进行可回滚的资源调整。

第七层:确认是不是网页本身慢

TTFB 正常不代表页面已经可用

当 HTML 很快返回,但用户仍然要等待数秒,问题往往位于浏览器侧:

  • 首屏图片过大或未使用合适格式。
  • JavaScript 文件体积大、执行时间长。
  • 脚本阻塞 HTML 解析。
  • 第三方统计、广告、客服或地图资源超时。
  • 字体加载阻塞文本显示。
  • 页面发起了大量串行接口请求。
  • DOM 节点过多,布局和样式计算耗时。
  • 图片、视频没有按需加载。

在浏览器 Network 面板中,先查看文档请求是否已经快速完成,再看后续资源。一个常见判断是:

第七层:确认是不是网页本身慢配图

  • 文档 TTFB 高:继续查服务器、应用和数据库。
  • 文档 TTFB 低,但 Content Download 长:检查响应体大小、压缩和链路。
  • 资源请求完成,但页面仍卡顿:切到 Performance 面板看脚本执行、长任务和布局。
  • 某个第三方域名长期 pending:临时阻断或替换该资源进行对比,不要直接把第三方延迟归咎于源站。

浏览器中的 LCP、FCP、INP 等指标描述的是用户实际看到页面和进行交互的体验,不等同于服务器 TTFB。服务器可以在 100 毫秒内返回 HTML,但如果首屏脚本要执行 2 秒,用户仍会感觉打开慢。

检查响应大小和压缩

可以用 curl 查看响应头和大小:

curl -sS -D - -o /dev/null \
  -H 'Accept-Encoding: gzip, br' \
  'https://www.example.com/assets/app.js'

关注 Content-Encoding、Content-Length、缓存头和内容类型。压缩是否有效,需要结合文件类型和客户端支持情况判断。已经压缩过的图片、视频和部分归档文件再次压缩收益通常有限,反而会增加 CPU 消耗。

不要把所有静态资源都合并成一个超大文件,也不要只追求减少请求数而忽略缓存更新、按需加载和首屏优先级。更合理的验证方式是先找出体积最大、阻塞最长或重复下载的资源,再进行单项优化,并用浏览器瀑布图和真实用户数据确认变化。

一套由外到内的排查流程

当网站正在变慢时,可以按以下顺序执行,避免一开始就重启服务或修改配置。

1. 建立基线

记录三个时间点:

  • 正常时的 DNS、连接、TLS、TTFB 和总耗时。
  • 当前故障时的同一组指标。
  • 恢复后的同一组指标。

同时记录测试地点、协议、入口 IP、URL 和 HTTP 状态码。没有基线时,所谓“变快”可能只是换了缓存或换了测试网络。

2. 先做外部对比

从至少两个网络环境请求同一个 URL,比较:

  • DNS 返回是否一致。
  • 是否命中不同 IP。
  • IPv4 与 IPv6 是否有明显差异。
  • connect、TLS 和 TTFB 哪一段变慢。
  • 静态资源和动态接口是否表现一致。

如果只有一个地区慢,优先看 DNS 调度、区域路由和边缘节点;如果所有地区同时慢,再转向入口、应用、数据库和主机资源。

3. 再做服务器侧时间对齐

用客户端请求时间、Web 访问日志和应用日志进行对齐。重点不是寻找一条“看起来最慢”的日志,而是确认同一个请求在各层花了多少时间:

一套由外到内的排查流程配图

  • 客户端到入口:由 curl 或浏览器时间反映。
  • 入口等待上游:由 Nginx 或网关字段反映。
  • 应用处理:由请求 ID 和应用分段日志反映。
  • 数据库调用:由慢查询和应用数据库耗时反映。
  • 响应传输:由入口总时长、响应大小和客户端下载时间反映。

4. 一次只验证一个假设

例如怀疑数据库慢,不要同时升级主机、清缓存、改连接池和重启应用。可以先选一条慢请求,检查其数据库耗时;确认后再在低风险条件下验证索引、查询范围或连接池设置。

如果需要改变配置,应遵循“备份当前值—小范围变更—观察—保留回滚”的顺序。涉及 DNS、缓存和 CDN 的变化,还要考虑缓存 TTL 和传播时间,不能在几分钟内连续多次改动后凭结果判断某一次变更有效。

如何确认已经定位到根因

定位根因至少要满足“现象、证据、修复后变化”三者一致。

例如:

  • 现象是部分地区首次访问延迟高;证据是这些地区解析到某个不可用或高延迟地址;修复后同一地区的 DNS 和连接耗时同步下降。
  • 现象是动态接口 TTFB 高;证据是入口很快连接应用,但应用日志显示数据库查询占据大部分时间;优化查询或恢复索引后,数据库耗时和 TTFB 同时下降。
  • 现象是接口正常但页面晚出现;证据是 HTML 返回很快,某个脚本执行时间长;延迟加载或拆分脚本后,前端交互指标改善。
  • 现象是连接阶段随机超时;证据是某个入口 IP 的 TCP 重传和连接失败率明显高于其他入口;摘除该入口后错误率恢复正常。

只有重启服务后暂时恢复,不能证明根因是“服务需要重启”。重启可能清空连接池、释放内存、结束锁等待或刷新缓存,但也会丢失现场。恢复后应继续查看重启前的日志、资源曲线和连接状态,避免下次故障再次依赖重启。

验证恢复时应使用与故障期间相同的 URL、网络、协议和测试方法,并持续观察一段时间。动态问题需要覆盖业务高峰或相同并发条件,否则短时间正常不代表根因已经消失。

常见误判与边界

Ping 很高不等于网页一定慢

ICMP 可能被限速或丢弃,HTTPS 请求却正常。判断网站速度应优先看 TCP、TLS 和 HTTP 分阶段耗时。反过来,ping 正常也不能排除应用等待和数据库慢。

CPU 不高不等于服务器没有瓶颈

锁等待、磁盘 I/O、线程池排队、连接池耗尽和外部依赖超时,都可能在 CPU 较低时发生。必须把 CPU、内存、I/O、连接和应用分段耗时放在一起看。

HTTP 200 不等于用户体验良好

请求可能等待了 5 秒后才返回 200。应同时观察 p95、p99、超时、取消请求和前端可用时间。

CDN 命中不等于源站健康

静态资源可能由 CDN 正常返回,但动态接口仍然回源失败;也可能 CDN 缓存掩盖了源站变慢。排查时要区分边缘响应、回源响应和源站直接处理时间。

直接访问 IP 不能简单替代域名访问

HTTPS 依赖 Host 和 SNI,负载均衡还可能按域名选择后端。用 IP URL 测试可能命中错误站点或证书,优先使用保留域名的 --resolve,并确保 IP 属于授权测试范围。

恢复后应保留的监控点

一次故障解决后,至少应留下能够再次回答“哪一层先变慢”的监控数据,而不只是一个总响应时间。

层级建议监控点发现异常时的方向
DNS解析耗时、失败率、SERVFAIL、A/AAAA 返回差异权威 DNS、递归解析、记录和调度
网络TCP 建连、TLS 握手、重传、连接失败率路由、入口 IP、IPv4/IPv6、边缘节点
Web 入口请求总耗时、上游耗时、499、5xx、缓存命中代理、负载均衡、缓存和上游连接
应用p50/p95/p99、线程池、队列、外部依赖代码、连接池、重试和超时
数据库慢查询、锁等待、连接数、磁盘延迟SQL、索引、事务和资源
主机CPU、内存、swap、I/O、文件描述符、网络错误虚拟机、容器、系统限制
前端LCP、INP、资源体积、长任务、第三方失败脚本、图片、字体和渲染

监控阈值不宜脱离自身基线。可以先用一段稳定时期建立正常范围,再对“相对基线明显升高”设置告警。例如入口 TTFB、应用 p95、数据库锁等待和 5xx 率同时升高时,告警应附带请求路径和时间窗口,方便直接关联日志。

最终目标不是记住某个固定耗时标准,而是让每次慢请求都能沿着 DNS、网络、Web 入口、应用、数据库和网页资源逐层缩小范围。只有把影响范围、分阶段耗时和服务端日志对齐,才能区分“服务器真的慢”“网络到不了”“DNS 返回异常”以及“服务器已经返回,但浏览器还没有把页面呈现出来”。