在浏览器输入一个网址后,请求通常要经过 DNS、网络连接、TLS、CDN 或反向代理,最后才到应用。返回的 HTML 也不是终点,浏览器还要继续下载样式、脚本、字体和图片。MDN 对网页工作方式的说明(在新标签页打开)也把 DNS、HTTP 请求、服务器响应和浏览器组装页面列为连续环节。

网页请求从浏览器经过 DNS、连接与 TLS、CDN、反向代理到达应用,再返回浏览器渲染的流程图
一次典型的 HTTPS 请求链路。缓存命中时,中间的部分步骤可能不会发生。

浏览器先拆解网址

以 https://example.com/posts/guide/?from=search#step-2 为例:

  • https 决定协议和默认端口;
  • example.com 是需要解析的主机名;
  • /posts/guide/ 是服务器会收到的路径;
  • from=search 是查询参数,可能影响 CDN 缓存和应用逻辑;
  • #step-2 只用于浏览器内定位,不会随 HTTP 请求发送。

浏览器还会检查已有的 DNS 结果、连接、HTTP 缓存、Service Worker 和 HSTS。页面刷新一次,并不代表整条链路都会重新执行。

DNS 找到的是入口,不一定是源站

本机没有可用缓存时,系统解析器会向递归 DNS 查询。递归 DNS 也没有缓存,才会沿根域、顶级域和权威 DNS 找到记录。

网站可能直接返回 A 或 AAAA 地址,也可能通过 CNAME 指向 CDN。浏览器连接的是最终解析出的入口,通常看不到入口之后还有哪些源站和内部网络。

dig +short example.com NS
dig +short www.example.com CNAME
dig +short www.example.com A
dig +short www.example.com AAAA

本机代理或特殊 DNS 可能返回合成地址。结果看起来不对时,可以指定公共解析器,或者直接追踪权威链路:

dig @1.1.1.1 example.com A
dig +trace example.com

A、AAAA、CNAME、TXT 和 CAA 的具体区别,见 DNS 记录怎么选。

建立连接后,HTTPS 还要完成 TLS

HTTP/1.1 和 HTTP/2 通常使用 TCP;HTTP/3 使用基于 UDP 的 QUIC。拿到入口地址后,客户端先建立传输连接,再为 HTTPS 完成 TLS 握手。

浏览器会检查证书是否覆盖当前域名、是否过期、证书链是否可信,并与服务端协商加密参数和应用层协议。证书名称错误发生在请求到达应用之前,因此应用日志里往往没有对应记录。

curl -sS -o /dev/null \
  -w 'http=%{http_version} code=%{http_code} remote=%{remote_ip}\n' \
  https://example.com/

openssl s_client -connect example.com:443 \
  -servername example.com </dev/null

CDN 和反向代理做的不是同一件事

CDN 更靠近访问者。缓存命中时,边缘节点可以直接返回文件;未命中时,才向源站取回内容。判断 CDN 是否工作,不能只看 CNAME,还要连续请求同一个 URL:

curl -sS -D - -o /dev/null https://cdn.example.com/path/image.webp
curl -sS -D - -o /dev/null https://cdn.example.com/path/image.webp

X-Cache、Age、ETag 和 Cache-Control 可以帮助判断内容是否来自预期源站、能否缓存,以及第二次请求是否命中。

反向代理通常位于源站入口。它按照域名和路径,把请求转发到正确的应用端口,并处理 HTTPS、跳转、压缩、WebSocket 和访问日志。出现 502 时,最有用的检查不是宿主机上的 curl localhost,而是确认代理所在的网络能否访问上游。

应用返回 HTML 后,页面还没加载完

应用可能继续访问缓存、数据库、对象存储或第三方 API。HTML 返回浏览器后,浏览器还要构建 DOM、下载资源、计算布局、执行脚本并绘制页面。

首字节耗时和页面可用时间要分开判断:

  • 首字节很慢:更可能卡在网络、CDN 回源、反向代理、应用或数据库;
  • 首字节正常但页面迟迟不可用:更可能是资源体积、请求数量、JavaScript 主线程或渲染问题。

用 curl 拆开页面各阶段耗时

curl -sS -o /dev/null \
  -w $'dns=%{time_namelookup}\nconnect=%{time_connect}\ntls=%{time_appconnect}\nttfb=%{time_starttransfer}\ntotal=%{time_total}\n' \
  https://example.com/

这些字段是累计时间,需要用相邻时间相减,才能看到某一段实际花了多久。各变量的准确含义以 curl --write-out 文档(在新标签页打开)为准;连接复用、代理和 HTTP/3 会改变部分阶段是否出现以及怎样计时。

使用 curl 的 DNS、连接、TLS、TTFB 和总耗时定位网页变慢位置的示意图
先找到变慢的区间,再打开对应系统的日志和指标。
变慢的区间近似计算优先查看
DNStime_namelookup解析器、权威 DNS、记录和 TTL
TCP 建连time_connect - time_namelookup路由、丢包、入口地域和端口
TLStime_appconnect - time_connect证书链、网络往返和会话复用
等待首字节time_starttransfer - time_appconnectCDN 回源、代理、应用和数据库
下载正文time_total - time_starttransfer内容体积、带宽和压缩

按报错位置缩小范围

现象先查哪里
找不到域名、解析失败NS、A/AAAA、CNAME 和本机 DNS
连接被拒绝或超时入口地址、端口、防火墙和安全组
证书名称或有效期错误DNS 指向、SNI 和入口证书
静态资源时新时旧CDN 缓存键、TTL、Age 和 ETag
502反向代理到上游的网络与端口
504上游处理时间、代理超时和慢查询
TTFB 正常但页面仍慢浏览器 Network 和 Performance 面板

按 DNS、连接、证书、CDN、代理、应用和浏览器的顺序从外向内排查。证书尚未完成握手时,数据库日志与当前故障无关。

保留 DNS 最终应答、客户端分段耗时,以及入口与应用日志中的同一请求。浏览器报错页或单次 ping 无法定位故障层级。

常见问题

在浏览器输入网址后,最先发生什么?

浏览器先解析 URL,并检查本地 DNS、已有连接和 HTTP 缓存。需要重新解析时,才通过系统解析器查询域名对应的入口地址。

DNS 完成后会直接连接源站吗?

不一定。DNS 可能把域名指向 CDN、负载均衡器或反向代理。客户端连接的是最终解析出的入口,再由入口决定是否访问源站。

TLS 握手和 HTTPS 是一回事吗?

TLS 握手负责身份验证、算法协商和密钥建立;握手完成后,HTTP 才在加密连接中传输。HTTPS 指的是这一整套组合。

TTFB 高就一定是后端慢吗?

不一定。TTFB 包含 DNS、建连、TLS、CDN 回源、代理等待和应用处理。先拆开各段耗时,再对照入口与应用日志定位慢点。

怎样判断请求是否经过 CDN?

先检查 CNAME,再看真实 GET 响应中的 CDN 特征头、缓存状态、Age 和 ETag。CNAME 正确只能说明 DNS 已指向 CDN,不能证明当前文件已经命中缓存。