浏览器访问 HTTPS URL 的纵向网络流程从解析 HTTPS URL 开始,依次检查本地缓存、解析域名、建立或复用安全连接、发送 HTTP 请求、 穿过边缘网络并由源站处理,最终由浏览器收到响应首字节。右侧标出缓存命中、Happy Eyeballs、 HTTP/3、连接复用和服务端等待等可能改变实际路径的分支。HTTPS NAVIGATION · URL TO FIRST RESPONSE BYTE01解析 HTTPS URLscheme · host · port · path规范化地址,并应用已知的 HSTS 策略02检查本地快速路径Service Worker · HTTP 缓存 · 连接池命中可复用响应时,后续网络步骤可以跳过可能提前结束缓存直接返回不产生新连接03解析域名浏览器 / 系统缓存 → 递归 DNS → 权威 DNS得到 A、AAAA 或 HTTPS 等资源记录地址竞争Happy Eyeballs协调 IPv6 / IPv404复用或建立安全连接TCP 三次握手 → TLS 1.3 握手验证证书与主机身份,协商密钥和 ALPN已有可用连接时,不必重复完整握手HTTP/3 分支QUIC 运行于 UDP传输与 TLS 1.3协同建立05发送 HTTP 请求方法 · 路径 · 请求头 · Cookie按 HTTP/1.1、HTTP/2 或 HTTP/3 编码传输连接与流复用HTTP/2 多路复用HTTP/1.1 持久连接06穿过网络与边缘层本地网关 → ISP → 互联网路由可能经过 CDN、WAF、负载均衡或反向代理07边缘命中或源站处理CDN 缓存,或网关 → 应用 → 数据层生成响应状态、响应头和正文数据等待阶段后端处理时间也是 TTFB 的一部分08浏览器收到响应首字节responseStart · TTFB 到达终点随后才进入响应接收、HTML 解析与渲染阶段本文边界到首字节为止不等于页面已渲染
浏览器本地阶段寻址与连接网络与服务端可能改变主线的分支

在地址栏输入 https://example.com/products?id=42 并按下回车,看起来只是让浏览器“打开一个页面”。实际上,在页面内容开始返回之前,浏览器可能需要解析地址、检查本地响应、寻找目标 IP、选择传输协议、建立加密通道,再让请求穿过边缘网络到达真正处理它的服务。

但这不是一条每次都完整执行的固定流水线。缓存可以让请求不出网,已有连接可以跳过 DNS、TCP 和 TLS,DNS 查询与候选地址连接可以交错进行,HTTP/3 又不经过 TCP。本文先沿一条便于理解的时间主线展开,再在每个节点说明真实路径可能怎样缩短、并行或分叉。

🧭 先明确起点与终点

本文的起点是浏览器已经得到一个 HTTPS URL,终点是浏览器收到响应的第一个字节,也就是 Navigation Timing 中的 responseStart 附近。

这个终点不等于“网页已经显示出来”。首字节到达后,浏览器还要继续接收响应体、解析 HTML、发现 CSS 和 JavaScript、构建 DOM 与 CSSOM、布局、绘制和合成。那些属于页面加载与渲染阶段,不在本文范围内。

还要区分三种描述:

  • 协议要求: RFC 或 Web 标准规定双方必须遵守的行为。
  • 常见实现: 主流浏览器和操作系统经常采用的缓存、连接池与并发策略。
  • 一次访问的实际路径: 受浏览器版本、代理、网络、缓存状态、服务器能力和隐私分区策略共同影响。

所以下文的编号表达的是因果关系和观察顺序,不承诺所有步骤在时间线上严格串行。

1️⃣ 浏览器先解析 URL

浏览器首先把输入解析成结构化 URL。以 https://example.com/products?id=42 为例:

部分作用
schemehttps要求使用受 TLS 保护的 HTTP
hostexample.com用于域名解析和服务器身份验证
port未显式填写,默认 443目标服务端口
path/productsHTTP 请求目标的一部分
queryid=42HTTP 请求目标的一部分

URL 中的 #fragment 不会发送给服务器,它只在客户端用于定位文档片段或交给前端逻辑处理。用户名、密码、非 ASCII 域名、百分号编码和相对路径还会触发额外的 URL 解析规则。

本文假设最终 URL 已经是 HTTPS。若用户输入的是 http:// 或省略了 scheme,浏览器可能先根据地址栏规则、历史记录、搜索策略或 HSTS 将其升级为 HTTPS。HSTS 预加载可以在发出明文 HTTP 请求之前完成升级,从而避免一次容易被劫持的 HTTP 跳转。

重定向发生在更晚的 HTTP 响应阶段。服务器若返回 301302303307308 和新的 Location,浏览器会解析新 URL,并对新目标重新执行必要步骤。新旧 URL 若主机不同,DNS、连接和 TLS 都可能重新发生。

🛑 请求可能根本不会出网

在“DNS 一定是第一步”之前,浏览器先进入 Fetch 与导航处理。这里存在几条本地快速路径。

Service Worker

如果当前站点在对应 scope 下有已激活的 Service Worker,导航请求可以触发它的 fetch 事件。Service Worker 可以:

  • 直接构造一个 Response
  • 从 Cache API 返回离线页面或已缓存资源。
  • 修改请求后继续访问网络。
  • 同时读取缓存和网络,采用先返回者或自定义回退策略。

因此 Service Worker 更像浏览器内部由站点代码控制的一层代理,不等同于普通 HTTP 缓存。长时间未运行的 Service Worker 还可能产生启动开销。

HTTP 缓存

若请求可以由新鲜的 HTTP 缓存响应满足,浏览器可以直接复用响应,无需连接源站。缓存项过期时,浏览器也可能发送带 If-None-MatchIf-Modified-Since 的条件请求;服务器返回 304 Not Modified 后继续复用本地正文。

开发者工具中常见的 memory cache、disk cache 是实现层面的存储标签,并不是 HTTP 规范定义的两套缓存语义。现代浏览器还会按顶级站点等维度对缓存和连接状态分区,以降低跨站跟踪风险。

已有连接

即使必须发出网络请求,浏览器也可能已经持有到目标源或可合并源的可用连接。此时域名信息、TCP、TLS 或 QUIC 不一定重新执行。在 Navigation Timing 中,DNS 和连接阶段的起止时间可能相同,这往往表示缓存或连接复用,而不是浏览器“漏记了耗时”。

2️⃣ 域名怎样变成目标地址

只有在需要网络访问且没有足够的可复用连接信息时,浏览器才需要把主机名转换成可连接的目标。

先查可用的本地信息

常见实现可能利用浏览器 DNS 缓存、操作系统解析器缓存、hosts 配置或安全 DNS 组件。具体查找顺序不是 Web 应用可以依赖的接口;企业策略、VPN、代理和浏览器的 DoH 设置都可能改变它。

如果没有可用结果,客户端把问题交给递归解析器。解析器会尽量使用自己的缓存;缓存未命中时,它才沿 DNS 委派关系查询根、顶级域和权威 DNS。对站点连接而言,常见结果包括:

  • A:IPv4 地址。
  • AAAA:IPv6 地址。
  • CNAME:别名,需要继续解析最终名称。
  • HTTPS / SVCB:可能提供替代端点、端口或应用协议提示。

TTL 控制 DNS 数据可以被缓存多久,但浏览器、操作系统和递归解析器可能设置自己的上下限。CDN 也可能根据递归解析器、EDNS Client Subnet、Anycast 或其他调度信息返回不同地址,所以“同一个域名”并不保证所有用户连接同一台机器。

DNS 不一定全部使用明文 UDP

传统 DNS 常使用 UDP 53;响应过大、需要重试或特定操作时可以使用 TCP。DoT 把 DNS 放进 TLS,DoH 则通过 HTTPS 发送查询。浏览器启用安全 DNS 后,查询路径甚至可能绕过操作系统默认递归解析器。

A 与 AAAA 不是简单地先等一个再等另一个

双栈客户端通常同时或交错获取 IPv6 与 IPv4 候选地址,再按策略排序并发起连接尝试。Happy Eyeballs 的目标是在偏好 IPv6 的同时,避免某个地址族故障导致用户长时间等待。它允许异步 DNS 查询和错峰连接竞争;某个候选连接成功后,其他尝试会被取消。

因此开发者看到一条最终连接,并不代表浏览器只查询过一个地址或只尝试过一次连接。

3️⃣ 复用连接,还是建立新连接

得到候选目标后,浏览器会结合代理配置、连接池、源站身份和协议能力选择路径。企业环境可能先执行 PAC 规则或连接显式代理;HTTPS 经过 HTTP 代理时,浏览器通常先用 CONNECT 建立隧道,再在隧道内与目标完成 TLS。

先决定下一跳

若目标不在本地链路,操作系统根据路由表选择网卡和下一跳网关。发送以太网或 Wi-Fi 帧前,还要通过 ARP(IPv4)或 Neighbor Discovery(IPv6)找到下一跳的链路层地址。家庭或办公网络常在出口执行 NAT,把私网地址和端口映射成公网连接。

这些动作可能已有缓存,例如 ARP/邻居表和 NAT 映射,因此不会在每次导航中都完整出现。

HTTP/1.1 与 HTTP/2 的常见 HTTPS 路径

如果没有可复用连接,传统路径先建立 TCP 连接。客户端发送 SYN,服务端返回 SYN-ACK,客户端回复 ACK。三次握手的主要目标是确认双方收发能力、初始化序列号并协商 TCP 选项。

TCP 成功后,HTTPS 再在这条可靠、按序的字节流上执行 TLS 握手。HTTP/1.1 可以在持久连接上连续发送请求;HTTP/2 则在一条连接里建立多个并发流,避免为每个请求单独创建连接。

HTTP/2 的多路复用不意味着 TCP 的队头阻塞消失:一个 TCP 包丢失时,后续字节必须等待重传,连接上的多个 HTTP/2 流都可能暂停。

HTTP/3 的路径不同

HTTP/3 使用 QUIC 作为传输,而 QUIC 通常运行在 UDP 之上。它把可靠传输、多路复用、拥塞控制和 TLS 1.3 握手组合在 QUIC 连接建立过程中,因此不存在“先 TCP 三次握手,再单独做 TLS,最后升级 HTTP/3”这条路径。

浏览器可以通过之前保存的替代服务信息、Alt-Svc、HTTPS DNS 记录或其他先验信息发现 HTTP/3 端点。实际实现还可能让 QUIC 与 TCP 路径竞争,并在 UDP 受阻时回退到 HTTP/2 或 HTTP/1.1。

QUIC 把可靠性放到流级别。某个流的数据丢失,不必像 TCP 那样阻塞同一连接中所有其他流;但拥塞控制、连接级流量控制和网络质量仍会影响整体性能。

4️⃣ TLS 1.3 怎样建立安全通道

截至 2026 年,TLS 1.3 的现行基础规范是 RFC 9846,它以兼容更新的方式取代了 RFC 8446。TLS 不只是“把内容加密”,它要为连接提供三类核心属性:服务器身份认证、机密性和完整性。

ClientHello 提供什么

客户端首先发送 ClientHello,其中通常包含:

  • 支持的 TLS 版本和密码算法参数。
  • 用于协商共享密钥的 key share。
  • 签名算法等能力列表。
  • SNI 或等价机制,用来表达目标主机。
  • ALPN,用来协商 h2http/1.1 等应用协议。
  • 会话恢复所需的 PSK 标识(如果存在)。

传统 SNI 会暴露主机名;支持并成功协商 ECH 时,客户端可以保护 ClientHello 中更敏感的部分。但不能假设每次连接都已使用 ECH。

服务端证明“我是谁”

服务端选择参数,返回自己的 key share,并在常见的证书认证模式下发送证书链、证书签名证明和 Finished 消息。浏览器需要验证的并不只是“证书能不能解密”,而是:

  • 证书链能否连接到本地信任的根。
  • 当前时间是否在证书有效期内。
  • 证书标识是否匹配请求主机名。
  • 签名和握手 transcript 是否有效。
  • 浏览器策略要求的证书透明度、撤销信息或其他约束是否满足。

撤销检查的具体机制和失败策略因浏览器而异,不能简单描述成每次握手都同步请求一次 OCSP。

验证成功后,双方从握手产生的共享材料派生流量密钥,后续 HTTP 数据以 TLS record 保护。被动观察者仍能看到 IP、端口、包长度和时序等元数据;TLS 不会把整条网络路径变得不可观察。

完整握手、恢复与 0-RTT

TLS 1.3 的常规完整握手通常可以在一次网络往返后让客户端发送受保护的应用数据。访问过该服务的客户端还可能使用会话票据恢复连接,减少计算和部分握手成本。

0-RTT 允许恢复连接时更早发送应用数据,但这部分 early data 不具备完整的重放保护。服务端和应用必须限制可接受的操作,不能把涉及资金、状态变更或不可幂等行为的请求默认当成安全的 0-RTT 数据。

5️⃣ HTTP 请求怎样发出去

安全通道可用后,浏览器根据 Fetch、Cookie、CSP、Referrer Policy 和凭据策略构造真正的导航请求。概念上它包含:

GET /products?id=42 HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml
Accept-Encoding: gzip, br, zstd
Cookie: session=...

这只是便于阅读的 HTTP/1.1 文本表示。实际传输形式取决于协议:

  • HTTP/1.1: 使用文本形式的起始行和头字段,默认支持持久连接。
  • HTTP/2: 把请求映射为二进制帧和流,使用 HPACK 压缩头字段,并在连接上多路复用。
  • HTTP/3: 把请求映射到 QUIC 流,使用 QPACK 压缩头字段。

浏览器不会无条件附带所有 Cookie。SecureSameSite、Domain、Path、过期时间和第三方 Cookie 策略都会参与选择。授权信息、客户端提示和优先级信息也可能改变请求头。

对于地址栏导航,常见方法是 GET,通常没有请求体。浏览器把请求交给已选择的连接后,数据还会被 TLS/QUIC、传输层、IP 层和链路层逐层封装。网卡发送的是帧,路由器转发的是 IP 包,远端 TLS 终止点最终恢复出 HTTP 消息。

6️⃣ 请求怎样到达 CDN 或源站

IP 包先到本地网关和运营商网络,再经过一系列路由器到达目标网络。BGP 参与不同自治系统之间的可达性与路径选择,但浏览器不会为每次请求亲自运行 BGP;它只把包交给操作系统选定的下一跳。

中途每台路由器根据转发表选择下一跳,IP 的 TTL 或 Hop Limit 随转发递减。实际去程和回程可以不对称,也可能因拥塞、故障或流量工程发生变化。

目标 IP 经常不是业务应用服务器本身,而是边缘入口:

浏览器

本地网关 / NAT

ISP 与互联网路由

CDN / WAF / 四层或七层负载均衡

反向代理 / API 网关

应用服务

这条链并非所有站点都具备。小型站点可能直接在一台服务器终止 TLS;大型站点则可能在 CDN 边缘终止客户端连接,再通过另一条受保护连接回源。客户端看到的 remoteAddress、证书和协议,只能直接描述客户端到 TLS 终止点这一段。

WAF 可以检查和阻断恶意请求,负载均衡把流量分配到健康实例,反向代理负责路由、压缩、缓存或协议转换。它们每增加一跳都可能增加处理与排队,但也能通过就近接入、连接池和缓存减少总体延迟。

7️⃣ 边缘命中与源站处理

到达 CDN 后,边缘节点会按缓存键、缓存新鲜度、请求方法、鉴权信息和站点规则判断能否直接响应。命中时,请求可以不回源,用户通常得到更低的网络往返延迟。

未命中或不可缓存时,边缘节点向源站发起请求。源站内部可能依次经过:

  1. 网关匹配路由和安全策略。
  2. 应用恢复会话并执行认证授权。
  3. 读取进程内缓存、Redis、数据库或下游服务。
  4. 生成状态码、响应头和正文。
  5. 把首批响应数据交回代理或客户端连接。

这同样不是必经清单。静态文件可能由 Web 服务器直接返回,SSR 页面可能等待多个后端,流式响应则可能先发送头部或页面骨架,再继续计算后续内容。

从客户端看,“Waiting for server response”不纯粹等于应用代码耗时。它还包含请求剩余传输、边缘与代理处理、回源网络、排队、后端计算,以及首批响应数据返回客户端的时间。

8️⃣ 什么叫“响应开始返回”

服务端或边缘节点开始响应时,会先产生状态码和响应头,然后才是响应体。例如:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: public, max-age=60
Content-Encoding: br

对 Navigation Timing 而言,responseStart 表示用户代理开始收到响应数据的时间点。传统 TTFB 通常按下面的方式理解:

TTFB = responseStart - navigationStart

它可能包含重定向、Service Worker 启动、缓存检查、DNS、连接、TLS、请求发送、服务端与边缘处理,以及首字节返回的网络时间。TTFB 高并不能直接证明数据库慢;DNS、丢包、连接建立、代理排队和跨区域回源都可能是原因。

103 Early Hints 让“第一个响应”更复杂

服务器可能先发送 103 Early Hints,提示浏览器预加载关键资源,再发送最终的 200 等响应。不同工具和浏览器版本对 TTFB 与 interim response 的呈现曾有差异。较新的 Resource/Navigation Timing 模型提供 interimResponseStartfinalResponseHeadersStart 等字段,用于区分首个临时响应和最终响应头;使用性能数据时应先确认目标浏览器与采集工具的口径。

本文到这里结束:浏览器已经开始收到响应,但页面尚未完成接收、解析或渲染。

🌡️ 冷访问、热访问与缓存命中

同一个 URL 的实际链路可能差别很大:

场景DNS新连接TLS / QUIC 握手服务器处理典型路径
首次冷访问通常需要通常需要完整握手通常需要最接近本文完整主线
DNS 已缓存可跳过外部查询可能需要可能需要通常需要从候选地址开始连接
已有 HTTP/2/3 连接通常无需重新暴露不需要不需要通常需要直接创建新流并发送请求
TLS/QUIC 会话恢复可能缓存需要新连接恢复握手通常需要连接成本低于完整握手
HTTP 缓存新鲜命中不需要不需要不需要不需要浏览器本地返回
Service Worker 本地响应由脚本策略决定不需要不需要不需要Worker 构造或读取响应
CDN 边缘命中客户端侧可能需要视连接状态视连接状态无需回源应用边缘直接返回

“刷新页面”也不是单一行为。普通刷新、强制刷新、禁用缓存、无痕窗口和关闭后重新打开浏览器,对 HTTP 缓存、Service Worker、DNS 缓存、连接池和会话票据的影响各不相同。

🧪 用开发者工具定位慢在哪里

Chrome、Edge、Firefox 等开发者工具的字段名称略有不同,但通常可以看到 Queueing/Stalled、DNS、Initial connection、SSL、Request sent、Waiting/TTFB 和 Content Download。

一个实用的判断顺序是:

  1. Queueing / Stalled 高: 检查浏览器连接限制、请求优先级、代理、Service Worker 和本机资源争用。
  2. DNS 高: 检查解析器、TTL、CNAME 链、DoH 路径和用户地域。
  3. Initial connection 高: 检查网络 RTT、IPv6/IPv4 失败回退、丢包和跨地域入口。
  4. SSL 高: 检查证书链、TLS 协商、会话恢复和 TLS 终止点距离。
  5. Waiting / TTFB 高: 再拆分 CDN 是否命中、回源耗时、代理排队和后端处理。
  6. Content Download 高: 这已经越过本文首字节边界,重点转向响应大小、压缩、带宽和流式传输。

页面内也可以读取 Navigation Timing:

const [navigation] = performance.getEntriesByType('navigation');

console.table({
  redirect: navigation.redirectEnd - navigation.redirectStart,
  dns: navigation.domainLookupEnd - navigation.domainLookupStart,
  tcpAndTls: navigation.connectEnd - navigation.connectStart,
  tls: navigation.secureConnectionStart > 0
    ? navigation.connectEnd - navigation.secureConnectionStart
    : 0,
  requestToFirstByte: navigation.responseStart - navigation.requestStart,
  totalTtfb: navigation.responseStart - navigation.startTime,
  nextHopProtocol: navigation.nextHopProtocol,
});

解释这些数字时注意:

  • DNS 或 connect 为 0,可能表示缓存、连接复用或时间字段折叠。
  • connectEnd - connectStart 通常包含传输连接和安全握手,不应再与 TLS 时间重复相加。
  • nextHopProtocol 描述浏览器直接连接的下一跳协议,不一定等于边缘到源站的协议。
  • 跨源资源需要服务器允许 Resource Timing 暴露详细信息;主文档导航不受完全相同的限制。
  • 实验室的一次瀑布图不能代表所有用户,应结合真实用户监控的地域和分位数。

🧠 最终心智模型

可以把整个过程压缩成五个问题:

  1. 本地已经有答案吗? Service Worker、HTTP 缓存或本地资源能否直接返回。
  2. 应该连接谁? DNS、代理、候选地址和边缘调度确定目标。
  3. 能否复用安全通道? 连接池决定复用,冷连接才建立 TCP + TLS 或 QUIC。
  4. 请求最终由谁处理? CDN、WAF、代理、网关或源站应用逐层决定。
  5. 首字节为何此时才到? 客户端准备、网络往返、排队和服务端处理共同组成等待。

因此,“输入 URL 后发生了什么”的标准答案不应只背诵 DNS → TCP → TLS → HTTP。更准确的模型是:先寻找可复用的本地与连接状态,再为缺失部分执行网络工作;浏览器、操作系统、边缘网络和源站共同决定最终路径。

📚 参考资料