kerikoの行星观察笔记
返回文章列表
2256 字12 分钟

从输入 URL 到页面展示:一次完整的 HTTP 请求经历了什么

技术分享#网络 / HTTP / DNS / 浏览器

每天我们都会在浏览器中输入无数个网址,按下回车,等待页面加载。这看似简单的操作背后,其实是一场跨越全球的计算机网络协作——从你的本地设备到远程服务器,经历了多个协议层的精密配合。

让我们跟随一个 URL 的旅程,看看它如何从字符变成眼前的页面。


第一步:URL 解析

浏览器首先需要理解你输入的是什么。

https://www.example.com/path/to/page?key=value
拆解为:
├─ 协议:https(加密传输)
├─ 主机:www.example.com
├─ 路径:/path/to/page
└─ 参数:key=value

如果输入的是 example.com(不带协议),浏览器会自动补全为 https://example.com(现代浏览器默认 HTTPS)。


第二步:DNS 解析——找到服务器的 IP 地址

域名是给人看的,机器需要 IP 地址才能通信。DNS(Domain Name System)就是互联网的“电话簿”。

DNS 解析流程

浏览器输入 www.example.com
1. 浏览器缓存检查
└─ 有缓存?直接返回 IP
2. 操作系统缓存检查
└─ 有缓存?直接返回 IP
3. 本地 DNS 服务器查询
└─ 有缓存?直接返回 IP
4. 递归查询 DNS 树
├─ 根 DNS 服务器 → 返回 .com 的顶级 DNS 地址
├─ .com 顶级 DNS → 返回 example.com 的权威 DNS 地址
└─ 权威 DNS → 返回 www.example.com 的 IP 地址
最终得到 IP:93.184.216.34

DNS 缓存层级

缓存位置 存活时间 说明
浏览器缓存 几分钟到几小时 最快,但受浏览器策略限制
操作系统缓存 几小时到几天 系统级缓存,所有应用共享
本地 DNS 服务器 几小时到几天 ISP 或企业提供的 DNS
权威 DNS 由 TTL 配置决定 域名持有者设置的最终答案

DNS 查询的典型耗时:20-200ms(有缓存时几乎为 0)。


第三步:TCP 三次握手——建立可靠连接

拿到 IP 地址后,浏览器需要与服务器建立 TCP 连接。

为什么是“三次”握手?

TCP 是可靠传输协议,需要确保双方都准备好收发数据。

客户端(浏览器) 服务器
│ │
│ ──── SYN ──────→ │ 第1次:客户端请求建立连接
│ "我要连你" │
│ │
│ ←─── SYN+ACK ──── │ 第2次:服务器确认并同意
│ "好的,你连吧" │
│ │
│ ──── ACK ──────→ │ 第3次:客户端确认
│ "收到,开始" │
│ │
══════ 连接建立 ════════

每一步的含义

步骤 报文 作用
第一次 SYN SYN=1, seq=x 客户端告诉服务器:我想连接,我的初始序列号是 x
第二次 SYN+ACK SYN=1, ACK=1, seq=y, ack=x+1 服务器回复:同意连接,我的序列号是 y,确认收到你的 x
第三次 ACK ACK=1, ack=y+1 客户端确认:收到你的 y,连接正式建立

典型耗时:一个 RTT(往返时间),从客户端到服务器的网络延迟。


第四步:TLS 握手——加密通道(HTTPS)

如果是 HTTPS(现代网站基本都是),在 TCP 连接后还需要 TLS 握手,确保通信安全。

TLS 1.2 握手过程(经典版本)

客户端 服务器
│ │
│ ── ClientHello ──→ │ 1. 客户端发送支持的加密算法列表
│ (支持的加密套件) │
│ │
│ ←─ ServerHello ── │ 2. 服务器选择加密套件
│ (选定的加密算法) │
│ │
│ ←─ Certificate ── │ 3. 服务器发送证书(包含公钥)
│ (数字证书) │
│ │
│ ── ClientKeyExchange ──→ │ 4. 客户端生成密钥,用公钥加密发送
│ (加密的预主密钥) │
│ │
│ ── ChangeCipherSpec ──→ │ 5. 客户端:开始加密通信
│ ── Finished ──→ │
│ │
│ ←─ ChangeCipherSpec ── │ 6. 服务器:开始加密通信
│ ←─ Finished ── │
│ │
══════ 加密通道建立 ══════════

TLS 1.3 的优化

TLS 1.3 将握手从 2 个 RTT 减少到 1 个 RTT

客户端 服务器
│ │
│ ── ClientHello + 密钥材料 ──→│ 1. 客户端直接发送密钥猜测
│ │
│ ←─ ServerHello + Finished ──│ 2. 服务器确认,加密通信开始
│ │
══════ 1-RTT 握手完成 ════════

如果是恢复会话(Session Resumption),甚至可以做到 0-RTT,直接发送加密数据。


第五步:发送 HTTP 请求

连接建立后,浏览器发送 HTTP 请求。

HTTP 请求结构

GET /path/to/page?key=value HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Language: zh-CN,zh;q=0.9
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: session_id=abc123
(请求体为空,GET 请求通常没有 body)

HTTP 方法对比

方法 作用 请求体 常见场景
GET 获取资源 浏览网页、查询数据
POST 提交数据 表单提交、上传文件
PUT 更新资源 修改配置、更新文档
DELETE 删除资源 删除记录

第六步:服务器处理请求

服务器收到请求后,会经历以下流程:

1. Web 服务器接收请求
└─ Nginx/Apache 接收 HTTP 报文
2. 请求路由分发
└─ 根据路径和配置,分发到对应处理模块
3. 业务逻辑处理
├─ 验证身份(Cookie/Token)
├─ 查询数据库
├─ 计算业务逻辑
└─ 组装响应数据
4. 生成响应内容
└─ 模板渲染或返回 JSON
5. 发送 HTTP 响应

HTTP 响应结构

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Cache-Control: max-age=3600
Date: Thu, 20 Mar 2026 10:00:00 GMT
<!DOCTYPE html>
<html>
<head>
<title>Example Page</title>
</head>
<body>
<h1>Hello World</h1>
...
</body>
</html>

常见状态码

状态码 类型 含义
200 成功 OK,请求成功
301/302 重定向 资源已移动,需访问新地址
304 缓存有效 资源未修改,使用缓存
400 客户端错误 请求格式错误
404 客户端错误 资源不存在
500 服务器错误 服务器内部错误

第七步:浏览器解析与渲染

浏览器收到 HTML 后,开始构建页面。这是最复杂的环节。

渲染流程

1. 解析 HTML → 构建 DOM 树
└─ 将标签转换为节点树结构
2. 解析 CSS → 构建 CSSOM 树
└─ 计算每个节点的样式规则
3. 合成渲染树(Render Tree)
└─ DOM + CSSOM = 可视节点树
4. 布局计算(Layout/Reflow)
└─ 计算每个节点的位置和大小
5. 绘制(Paint)
└─ 将节点绘制为像素
6. 合成(Composite)
└─ 将各层合成最终页面
7. 显示在屏幕上

关键概念

概念 说明 影响
DOM 树 HTML 结构的节点表示 节点数量影响解析速度
CSSOM 树 样式规则的节点表示 CSS 复杂度影响渲染速度
渲染树 DOM + CSSOM,只包含可见节点 不可见元素(如 <head>)不参与
Layout 计算位置和大小 DOM 变化触发重新布局(重排)
Paint 绘制像素到图层 样式变化触发重新绘制(重绘)

阻塞问题

JavaScript 会阻塞渲染

<html>
<body>
<h1>Hello</h1>
<script src="large.js"></script>
<!-- 阻塞后续解析 -->
<p>World</p>
<!-- 等脚本执行完才解析 -->
</body>
</html>

解决方案:

<script src="large.js" async></script>
<!-- 异步加载,不阻塞 -->
<script src="large.js" defer></script>
<!-- 延迟执行,DOM 解析完后运行 -->

完整时间线

让我们看一个典型请求的时间分解:

0ms │ 用户输入 URL,按下回车
50ms │ DNS 查询完成(有缓存时更快)
100ms │ TCP 三次握手完成(1 RTT)
200ms │ TLS 握手完成(HTTPS,1-2 RTT)
250ms │ HTTP 请求发送到达服务器
350ms │ 服务器处理完成,开始发送响应
500ms │ 第一个字节到达浏览器(TTFB)
600ms │ HTML 文档下载完成
800ms │ DOM 树构建完成
900ms │ CSSOM 树构建完成
1000ms │ 首次布局和绘制完成
1200ms │ 图片、脚本等资源加载完成
1500ms │ 页面完全加载

网络协议层级视角

从 OSI 模型看整个过程:

OSI 层级 协议 作用
应用层 HTTP、DNS 用户数据交互、域名解析
表示层 TLS 加密与解密
传输层 TCP 可靠传输、端口区分
网络层 IP 路由寻址、IP 地址
数据链路层 Ethernet/Wi-Fi MAC 地址、物理传输
物理层 电信号/光信号 比特流传输

每个层级都有明确的职责,共同完成从“输入 URL”到“看到页面”的旅程。


总结

从输入 URL 到页面展示,经历了七个关键步骤:

URL 解析 → DNS 解析 → TCP 握手 → TLS 握手 → HTTP 请求 → 服务器处理 → 浏览器渲染

每个步骤都有其必要性:

  • DNS:域名到 IP 的翻译
  • TCP:确保数据可靠传输
  • TLS:保护数据不被窃听
  • HTTP:约定请求和响应格式
  • 渲染:将数据变成可视内容

理解这些过程,能帮助你:

  • 优化网站性能:知道哪个环节慢,针对性优化
  • 排查网络问题:DNS 解析失败?连接超时?证书错误?
  • 理解安全机制:HTTPS 如何保护通信?

下次输入网址按下回车时,你可以想象这场发生在毫秒级时间内的全球协作——从你的设备出发,穿越 DNS 树、跨越 TCP 连接、经过加密隧道、抵达服务器、返回页面,最终在你眼前呈现。

这就是互联网的魅力:复杂的技术协作,换来简单的用户体验。

评论