HTTP 八股文:从三次握手到浏览器渲染的硬核拆解

"HTTP 是互联网的空气------你平时感觉不到它的存在,但没有它你什么都做不了。"

作为一个后端工程师,你可以不懂量子力学,但不能不懂 HTTP。面试里,从"GET 和 POST 的区别"到"HTTP/2 的多路复用原理",从"三次握手为什么是三次"到"HTTPS 的 TLS 握手过程"------这些问题你答不上来,基本就凉了。本文从最底层开始,把 HTTP 和相关网络知识给你掰开了揉碎了讲一遍。


📑 目录

  1. [HTTP 是什么?](#HTTP 是什么?)
  2. [HTTP 报文详解](#HTTP 报文详解)
  3. [HTTP 方法:不只是 GET 和 POST](#HTTP 方法:不只是 GET 和 POST)
  4. [HTTP 状态码:服务器的心情表达](#HTTP 状态码:服务器的心情表达)
  5. [HTTP Header:请求的「身份证」](#HTTP Header:请求的「身份证」)
  6. [HTTP 版本演进:从 0.9 到 3.0](#HTTP 版本演进:从 0.9 到 3.0)
  7. [TCP 基础:HTTP 的地基](#TCP 基础:HTTP 的地基)
  8. [HTTPS 与 TLS:加密通信](#HTTPS 与 TLS:加密通信)
  9. DNS:互联网的电话簿
  10. [Cookie、Session 与 Token](#Cookie、Session 与 Token)
  11. [HTTP 缓存机制](#HTTP 缓存机制)
  12. 跨域问题(CORS)
  13. [HTTP 连接管理](#HTTP 连接管理)
  14. [从输入 URL 到页面渲染的全过程](#从输入 URL 到页面渲染的全过程)
  15. 面试高频问题速查
  16. 参考文献

1. HTTP 是什么?

图1:HTTP 请求-响应模型 ------ 一问一答的通信艺术

1.1 一句话定义

HTTP(HyperText Transfer Protocol,超文本传输协议)是客户端和服务端之间通信的规则。它定义了:客户端怎么发请求、服务端怎么返响应、数据的格式是什么样的。

1.2 核心特点

无状态(Stateless)。 这是 HTTP 最重要的特点,也是面试最爱问的。每次请求都是独立的------服务器不会记住你上一次请求了什么。就像你每次都去同一家餐厅,但服务员每次都问你"请问您几位?"------他不记得你昨天来过。

为什么这么设计?因为无状态让服务器可以水平扩展------任何一台服务器都能处理任何请求,不需要共享状态。但在实际应用中,我们经常需要状态(比如登录状态),所以有了 Cookie、Session、Token 等机制来"模拟"有状态。

基于请求-响应模型。 客户端发请求,服务器返响应。在 HTTP/1.x 中,通信是半双工的------同一时刻只能有一方在说话。HTTP/2 引入了服务器推送,但本质上还是请求-响应模型。

可扩展。 HTTP 的 Header 是可扩展的------你可以添加自定义的 Header 字段,服务器和客户端都可以理解。这就是为什么 HTTP 能活 30 多年------它的设计足够灵活,可以通过扩展来适应新需求。

1.3 HTTP 在网络协议栈中的位置

层次 协议 作用 HTTP 的位置
应用层 HTTP, FTP, SMTP, DNS 应用程序通信 ← HTTP 在这里
传输层 TCP, UDP 端到端可靠传输 HTTP 依赖 TCP
网络层 IP 路由和寻址 IP 地址
数据链路层 Ethernet, Wi-Fi 帧传输 MAC 地址
物理层 光纤、电缆 比特流传输 电信号

表1:HTTP 在网络协议栈中的位置

HTTP 是应用层协议------它不关心数据怎么从A传到B(那是TCP和IP的事),它只关心数据的格式和语义。就像你写信------信的内容是应用层,邮局负责传输是传输层和网络层。


2. HTTP 报文详解

2.1 请求报文结构

复制代码
GET /api/users?page=1 HTTP/1.1          ← 请求行(方法 + URL + 版本)
Host: example.com                        ← 请求头
Accept: application/json
Authorization: Bearer eyJhbG...
Content-Type: application/json
Cookie: session_id=abc123
                                            ← 空行(分隔Header和Body)
{"name": "张三"}                          ← 请求体(GET没有Body)

2.2 响应报文结构

复制代码
HTTP/1.1 200 OK                           ← 状态行(版本 + 状态码 + 原因短语)
Content-Type: application/json            ← 响应头
Content-Length: 42
Cache-Control: max-age=3600
Set-Cookie: session_id=xyz789; HttpOnly
                                            ← 空行
{"id": 1, "name": "张三"}                 ← 响应体

2.3 报文的组成部分

部分 请求报文 响应报文 说明
起始行 请求行 状态行 描述请求/响应的基本信息
Header 请求头 响应头 元数据(Content-Type等)
空行 CRLF CRLF 分隔Header和Body
Body 请求体 响应体 实际传输的数据

表2:HTTP报文结构

一个关键细节:Header和Body之间必须有一个空行(CRLF)。如果没有空行,服务器不知道Header在哪里结束、Body在哪里开始。这是HTTP协议的基本语法。


3. HTTP 方法:不只是 GET 和 POST

3.1 九种 HTTP 方法

方法 语义 幂等 安全 有Body 典型用途
GET 获取资源 获取网页、API查询
POST 提交数据 创建资源、表单提交
PUT 替换资源 更新整个资源
PATCH 部分更新 更新资源的部分字段
DELETE 删除资源 可选 删除资源
HEAD 获取Header 检查资源是否存在
OPTIONS 查询支持的方法 CORS预检请求
TRACE 回显请求 调试用(生产禁用)
CONNECT 建立隧道 HTTPS代理

表3:HTTP九种方法

幂等:同一个请求执行多次,效果和执行一次相同。GET是幂等的------你刷新页面10次,页面内容一样(假设没有副作用)。POST不是幂等的------你提交订单10次,就创建了10个订单。

3.2 GET vs POST:面试必问

这是面试中最经典的HTTP问题。很多人只知道"GET参数在URL里,POST参数在Body里",但这只是表面区别。

维度 GET POST
语义 获取资源 提交数据
幂等
安全 是(只读) 否(可能有副作用)
参数位置 URL查询字符串 请求体
参数长度 浏览器限制约2048字符 理论上无限制
缓存 可以被缓存 默认不缓存
书签 可以收藏为书签 不行
编码 URL编码 支持多种编码(JSON、FormData等)
TCP数据包 一个(Header+URL一起发) 可能两个(先发Header,再发Body)

表4:GET vs POST 详细对比

一个容易被忽略的区别:语义。GET的语义是"获取资源"------它不应该有副作用(不改变服务器状态)。POST的语义是"提交数据"------它可能创建新资源、触发处理流程等。RESTful API就是基于这个语义来设计的。

3.3 RESTful API 设计

操作 HTTP方法 URL 示例
获取所有用户 GET /users GET /users
获取单个用户 GET /users/{id} GET /users/42
创建用户 POST /users POST /users
更新用户 PUT /users/{id} PUT /users/42
部分更新 PATCH /users/{id} PATCH /users/42
删除用户 DELETE /users/{id} DELETE /users/42

表5:RESTful API设计规范


4. HTTP 状态码:服务器的心情表达

图2:HTTP状态码五大类 ------ 1xx到5xx,服务器的五种心情

4.1 五大类状态码

状态码是三位数字,第一位表示类别:

类别 含义 常见例子 类比
1xx 信息性 100 Continue, 101 Switching "收到了,继续"
2xx 成功 200 OK, 201 Created "搞定了!"
3xx 重定向 301, 302, 304 "去找别人吧"
4xx 客户端错误 400, 401, 403, 404 "你的问题"
5xx 服务端错误 500, 502, 503 "我的问题"

表6:HTTP状态码五大类

4.2 面试必背状态码详解

200 OK。 最常见的状态码。请求成功,返回了请求的数据。

201 Created。 资源创建成功。POST请求创建新资源后应该返回201,同时在Location头中返回新资源的URL。

204 No Content。 请求成功,但没有返回内容。DELETE请求成功后通常返回204------你删了东西,没什么好返回的。

301 Moved Permanently。 资源永久搬家了。浏览器会自动跳转到新地址,搜索引擎会更新链接。下次请求直接去新地址。

302 Found。 资源临时搬家。浏览器会自动跳转,但下次请求还是来老地方找。302是临时的,301是永久的。

304 Not Modified。 资源没变过,用缓存吧。这是缓存机制的核心------服务器告诉客户端"你手里的版本还是最新的,不用重新下载"。省带宽神器。

400 Bad Request。 请求写错了。比如JSON格式错误、缺少必填参数。服务器看不懂你的请求。

401 Unauthorized。 你没有认证(没有登录)。需要提供有效的身份凭证(如Token)。

403 Forbidden。 你认证了但没有权限。你登录了,但这个资源你不能访问。

404 Not Found。 资源不存在。最熟悉的陌生人------每个互联网用户都见过它。

405 Method Not Allowed。 方法不允许。比如你用DELETE去访问一个只支持GET的URL。

500 Internal Server Error。 服务器内部出bug了。最通用的服务端错误。

502 Bad Gateway。 网关(如Nginx)收到了后端服务器的无效响应。通常意味着后端服务挂了。

503 Service Unavailable。 服务器暂时不可用(过载或维护)。通常可以稍后重试。

504 Gateway Timeout。 网关等待后端服务器响应超时。


5. HTTP Header:请求的「身份证」

Header 是 HTTP 报文的元数据------描述了请求/响应的各种属性。

5.1 通用 Header

Header 说明 示例
Content-Type Body的数据类型 application/json, text/html
Content-Length Body的字节数 42
Date 报文的日期时间 Thu, 01 Jan 2026 00:00:00 GMT
Connection 连接管理 keep-alive, close
Cache-Control 缓存策略 max-age=3600, no-cache

表7:通用Header

5.2 请求 Header

Header 说明 示例
Host 目标主机名(HTTP/1.1必须) example.com
Accept 客户端能接受的响应类型 text/html, application/json
Accept-Encoding 能接受的压缩方式 gzip, deflate, br
Authorization 身份凭证 Bearer eyJhbG...
Cookie 客户端存储的Cookie session_id=abc123
User-Agent 客户端信息 Mozilla/5.0 ...
Referer 来源页面URL https://example.com/prev
If-None-Match 协商缓存(ETag) "abc123"
If-Modified-Since 协商缓存(时间) Thu, 01 Jan 2026 00:00:00 GMT

表8:请求Header

5.3 响应 Header

Header 说明 示例
Set-Cookie 设置Cookie session_id=xyz; HttpOnly
ETag 资源的"指纹" "abc123"
Last-Modified 资源最后修改时间 Thu, 01 Jan 2026 00:00:00 GMT
Location 重定向目标URL https://example.com/new
Access-Control-Allow-Origin CORS允许的源 * 或 https://trusted.com
Strict-Transport-Security 强制HTTPS max-age=31536000

表9:响应Header

5.4 Content-Type 常见值

Content-Type 说明 使用场景
text/html HTML文档 网页
text/plain 纯文本 文本文件
application/json JSON数据 API
application/xml XML数据 旧式API
application/x-www-form-urlencoded 表单数据 HTML表单提交
multipart/form-data 文件上传 上传文件
application/octet-stream 二进制流 下载文件

表10:Content-Type常见值


6. HTTP 版本演进:从 0.9 到 3.0

图3:HTTP版本演进 ------ 30年五代进化

6.1 HTTP/0.9(1991)

HTTP 的"太爷爷"。只有 GET 方法,没有 Header,只能传输 HTML。一行命令就搞定了:

复制代码
GET /index.html

服务器返回:

复制代码
<html>...</html>

就这么简单。没有状态码,没有Header,没有图片,没有CSS,没有JavaScript。

6.2 HTTP/1.0(1996)

引入了 Header、状态码、多种方法(GET/POST/HEAD)。但有一个致命问题:非持久连接------每个请求都要重新建立 TCP 连接。请求一个包含10张图片的网页,需要建立11个 TCP 连接(1个HTML + 10张图片)。三次握手的开销是巨大的。

6.3 HTTP/1.1(1997)

HTTP/1.1 是目前使用最广泛的版本(虽然已经 27 岁了)。关键改进:

持久连接(Keep-Alive)。 默认开启,一个 TCP 连接可以发送多个请求。不用每次都重新握手。

管线化(Pipelining)。 客户端可以连续发送多个请求,不用等前一个响应返回。但实际中很少使用------因为响应必须按请求顺序返回(队头阻塞),如果第一个响应很慢,后面的都要等。

分块传输(Chunked Transfer)。 服务器可以分块发送数据,不用等全部准备好。这对大文件和动态生成的内容很有用。

Host 头。 一个IP地址可以托管多个域名(虚拟主机)。Host头告诉服务器你要访问哪个域名。

6.4 HTTP/2(2015)

HTTP/2 是一次重大升级,核心创新是二进制分帧多路复用

二进制分帧。 HTTP/1.x 是纯文本协议(人可读),HTTP/2 改为二进制格式。数据被拆分成更小的"帧"(Frame),每个帧有类型、长度、标志位等元数据。

多路复用(Multiplexing)。 这是 HTTP/2 最重要的特性。在同一个 TCP 连接上,多个请求/响应可以同时传输,互不干扰。彻底解决了 HTTP/1.1 的应用层队头阻塞。

头部压缩(HPACK)。 HTTP 头部有很多重复的字段(如 Cookie、User-Agent),HPACK 算法用索引表来压缩这些重复信息。

服务器推送(Server Push)。 服务器可以主动向客户端推送资源,不用等客户端请求。比如客户端请求 HTML,服务器可以主动推送 CSS 和 JS。

但 HTTP/2 有一个新问题:TCP 层的队头阻塞。 虽然应用层可以多路复用,但底层的 TCP 是字节流协议------如果一个 TCP 包丢了,所有流都要等它重传。这就是 HTTP/3 要解决的问题。

6.5 HTTP/3(2022)

HTTP/3 用 QUIC 协议替代了 TCP。QUIC 基于 UDP,但加入了可靠性、加密和多路复用。

0-RTT 建连。 首次连接只需要 1-RTT(比 TCP+TLS 的 3-RTT 快),后续连接可以 0-RTT------数据在握手的同时就开始传输。

真正的多路复用。 QUIC 在传输层就支持多路复用------一个连接中的多个流是独立的,一个流的丢包不会影响其他流。彻底解决了队头阻塞。

连接迁移。 TCP 连接由四元组(源IP、源端口、目的IP、目的端口)标识。当你从 Wi-Fi 切换到 4G 时,IP 地址变了,TCP 连接就断了。QUIC 用连接 ID 来标识连接,IP 变了连接还在。

6.6 版本对比总结

版本 年份 传输层 队头阻塞 建连延迟 多路复用 头部压缩
1.0 1996 TCP 1.5RTT+TLS
1.1 1997 TCP 有(管线化) 1.5RTT+TLS
2 2015 TCP TCP层有 1.5RTT+TLS HPACK
3 2022 QUIC/UDP 彻底解决 0-1RTT QPACK

表11:HTTP版本对比


7. TCP 基础:HTTP 的地基

图4:TCP三次握手与四次挥手 ------ 网络连接的生与死

7.1 为什么 HTTP 需要 TCP?

HTTP 自己不管传输------它只管数据格式。数据的可靠传输由 TCP 来保证。TCP 提供:

  • 可靠性:数据不丢失、不重复、按顺序到达
  • 面向连接:通信前需要建立连接(三次握手)
  • 流量控制:防止发送方发太快淹没接收方
  • 拥塞控制:防止网络拥塞

7.2 三次握手(Three-way Handshake)

建立 TCP 连接需要三次握手:

第一次握手(SYN)。 客户端发一个 SYN 包(seq=x),表示"我要连接你"。此时客户端进入 SYN_SENT 状态。

第二次握手(SYN+ACK)。 服务器收到后,返回一个 SYN+ACK 包(seq=y, ack=x+1),表示"好的,我同意连接,你还在吗?"。此时服务器进入 SYN_RCVD 状态。

第三次握手(ACK)。 客户端收到后,返回一个 ACK 包(ack=y+1),表示"我在,连接建立!"。双方进入 ESTABLISHED 状态。

为什么是三次而不是两次? 面试必问。核心原因是:防止已失效的连接请求到达服务器

想象一下:客户端发了一个 SYN,但网络延迟导致它很久才到达服务器。客户端以为丢了,又发了一个新的 SYN,这次正常建立了连接并完成了通信。然后那个迟到的旧 SYN 终于到了服务器------如果是两次握手,服务器会以为这是一个新连接并分配资源,但客户端根本不知道,资源就浪费了。三次握手让客户端在第三步确认"我确实要连接",避免了这种情况。

7.3 四次挥手(Four-way Handshake)

断开 TCP 连接需要四次挥手:

第一次挥手(FIN)。 客户端发 FIN,表示"我不发数据了"。

第二次挥手(ACK)。 服务器确认收到,但可能还有数据没发完。

第三次挥手(FIN)。 服务器也发完数据了,发 FIN 表示"我也不发了"。

第四次挥手(ACK)。 客户端确认,然后等待 2MSL(Maximum Segment Lifetime)后关闭。

为什么是四次而不是三次? 因为 TCP 是全双工的------两个方向的数据流是独立的。关闭连接时,每个方向都要单独关闭。客户端说"我不发了",但服务器可能还有数据没发完,所以要先确认,等发完了再发自己的 FIN。

7.4 TCP 与 UDP

特性 TCP UDP
连接 面向连接 无连接
可靠性 可靠(确认+重传) 不可靠
顺序 保证顺序 不保证
速度 较慢
头部开销 20字节 8字节
用途 HTTP、文件传输 DNS、视频、游戏、QUIC

表12:TCP vs UDP

HTTP/3 的 QUIC 协议就是在 UDP 之上实现可靠性------它用 UDP 的速度,加上自己的可靠传输和加密机制。这就像"在高速公路上建铁路"------利用UDP的高效传输,加上自己的可靠保障。


8. HTTPS 与 TLS:加密通信

图5:HTTPS = HTTP + TLS ------ 加密通信的三重保护

8.1 为什么需要 HTTPS?

HTTP 是明文传输的------你发的每一个字节,中间人(如路由器、ISP、公共Wi-Fi的管理员)都能看到。这意味着:

  • 密码、Token、Cookie 全部裸奔
  • 中间人可以篡改你收到的内容(注入广告、修改页面)
  • 你不知道对面的服务器是不是真的(可能是钓鱼网站)

HTTPS 通过 TLS(Transport Layer Security)协议解决了这三个问题。

8.2 TLS 握手过程(TLS 1.3)

TLS 1.3 将握手从 2-RTT 优化到 1-RTT:

  1. ClientHello:客户端发送支持的加密套件列表 + 客户端随机数 + 支持的TLS版本
  2. ServerHello:服务器选定加密套件 + 服务器随机数 + 服务器证书 + 服务器公钥
  3. 客户端验证证书:用CA的公钥验证服务器证书是否合法
  4. 密钥交换:客户端生成预主密钥,用服务器公钥加密后发送
  5. 生成会话密钥:双方用三个随机数(客户端随机数+服务器随机数+预主密钥)生成对称加密的会话密钥
  6. 加密通信开始:后续所有数据都用对称加密传输

为什么要用三个随机数? 因为任何一个随机数被猜到都不会影响安全性。这叫做"前向安全性"(Forward Secrecy)。

8.3 对称加密 vs 非对称加密

类型 原理 速度 用途
对称加密 加密解密用同一个密钥 数据传输(AES)
非对称加密 公钥加密,私钥解密 密钥交换(RSA, ECDHE)

表13:对称加密 vs 非对称加密

TLS 握手用非对称加密来安全地交换密钥,然后用对称加密来传输数据。就像你用保险箱(非对称加密)把钥匙寄给对方,然后双方用这把钥匙(对称加密)来通信。

8.4 数字证书与 CA

数字证书是服务器的"身份证"------它证明"这个公钥确实属于 example.com"。

证书的信任链:

  1. 根证书:内置在操作系统/浏览器中(如 DigiCert, Let's Encrypt)
  2. 中间证书:由根证书签发
  3. 服务器证书:由中间证书签发

浏览器验证证书时,会沿着信任链一直验证到根证书。如果任何一个环节有问题(过期、域名不匹配、未被信任的CA),浏览器会显示"不安全"警告。


9. DNS:互联网的电话簿

9.1 DNS 是什么?

DNS(Domain Name System)把域名(如 example.com)翻译成 IP 地址(如 93.184.216.34)。没有 DNS,你就得记住每个网站的 IP 地址------就像没有电话簿,你就得记住每个人的电话号码。

9.2 DNS 解析过程

你在浏览器输入 www.example.com,DNS 解析过程如下:

  1. 浏览器缓存:浏览器先查自己的 DNS 缓存
  2. 操作系统缓存:浏览器没有,查操作系统的 DNS 缓存(hosts文件)
  3. 本地 DNS 服务器:操作系统没有,问本地 DNS 服务器(通常是路由器或ISP提供的)
  4. 递归查询 :本地 DNS 服务器也没有,开始递归查询:
  5. 返回结果:权威服务器返回 IP 地址
  6. 缓存:各级缓存结果(根据 TTL 过期时间)

9.3 DNS 记录类型

记录类型 说明 示例
A 域名→IPv4地址 example.com → 93.184.216.34
AAAA 域名→IPv6地址 example.com → 2606:2800:...
CNAME 域名别名 www.example.comexample.com
MX 邮件服务器 example.commail.example.com
NS 域名服务器 example.comns1.example.com
TXT 文本记录 SPF、DKIM等

表14:DNS记录类型


10. Cookie、Session 与 Token

图6:身份验证三兄弟 ------ 解决HTTP无状态问题的三种方案

10.1 为什么需要它们?

HTTP 是无状态的------服务器不记得你是谁。但很多场景需要状态:登录、购物车、个性化设置。Cookie、Session、Token 就是为了在无状态的 HTTP 上"模拟"有状态。

Cookie 是服务器通过 Set-Cookie 响应头设置在浏览器里的小数据。浏览器每次请求都会自动带上 Cookie。

复制代码
# 服务器设置Cookie
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax

# 浏览器每次请求自动带上
Cookie: session_id=abc123

关键属性:

  • HttpOnly:JavaScript 不能读取(防 XSS)
  • Secure:只能通过 HTTPS 发送
  • SameSite:防止 CSRF 攻击(Lax/Strict/None)
  • Path:Cookie 的作用路径
  • Domain:Cookie 的作用域名
  • Expires/Max-Age:过期时间

10.3 Session

Session 是服务端存储的用户状态。浏览器只存一个 Session ID(通常放在 Cookie 里),用户数据存在服务器的内存或数据库中。

优点: 敏感数据不出服务器,更安全。

缺点: 分布式环境下需要共享Session(用Redis等共享存储),服务器重启可能丢失。

10.4 Token(JWT)

JWT(JSON Web Token)是一种无状态的身份凭证。用户信息编码在 Token 本身中,服务端不需要存储。

复制代码
# JWT的结构(三部分用.分隔)
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo0Mn0.signature
   ↑ Header        ↑ Payload         ↑ Signature

优点: 天然支持分布式、跨域、无状态。

缺点: Token 一旦签发无法撤销(除非用黑名单),Token 体积比 Session ID 大。

10.5 三者对比

维度 Cookie Session Token (JWT)
存储位置 浏览器 服务器 浏览器/客户端
状态 有状态 有状态 无状态
安全性 中(可被XSS/CSRF) 高(但无法撤销)
分布式 不适用 需要共享存储 天然支持
跨域 受限 受限 支持
适用场景 简单状态 传统Web API、微服务、移动端

表15:Cookie vs Session vs Token


11. HTTP 缓存机制

图7:HTTP缓存决策流程 ------ 强缓存 + 协商缓存

11.1 为什么需要缓存?

  • 减少延迟:直接用本地缓存,不用等网络传输
  • 减少带宽:不需要重复下载相同的资源
  • 减轻服务器压力:减少服务器的请求量

11.2 强缓存(Strong Caching)

强缓存是最"霸道"的缓存------在有效期内,浏览器直接用缓存,完全不问服务器。

Cache-Control: max-age=3600。 资源在3600秒内有效。浏览器会直接从磁盘/内存缓存中读取,连网络请求都不发。状态码是 200 (from cache)。

Expires: Thu, 01 Jan 2027 00:00:00 GMT。 资源在这个时间之前有效。用的是绝对时间,有 2038 问题(类似 Y2K)。现在推荐用 Cache-Control 的 max-age。

Cache-Control 的其他指令:

  • no-cache:不用直接缓存,但可以存(需要协商缓存验证)
  • no-store:完全不缓存
  • public:任何中间节点都可以缓存
  • private:只有浏览器可以缓存(中间代理不行)
  • must-revalidate:缓存过期后必须验证

11.3 协商缓存(Conditional Caching)

当强缓存过期后,浏览器会向服务器发请求验证------"我手里的版本还是最新的吗?"

ETag + If-None-Match。 服务器第一次返回资源时,会生成一个 ETag(资源的"指纹",通常是内容的哈希值)。浏览器下次请求时,在 If-None-Match 头中带上这个 ETag。服务器比对------如果没变,返回 304(不返回Body);如果变了,返回 200 和新资源。

Last-Modified + If-Modified-Since。 服务器返回资源的最后修改时间。浏览器下次请求时,在 If-Modified-Since 头中带上这个时间。服务器比对------如果没改过,返回 304。

ETag vs Last-Modified:

  • ETag 更精确(内容级),Last-Modified 是秒级
  • ETag 优先级更高(两者同时存在时用 ETag)
  • ETag 计算有开销(哈希),Last-Modified 很便宜

11.4 缓存策略最佳实践

资源类型 缓存策略 原因
HTML no-cache(协商缓存) HTML是入口,需要最新版本
CSS/JS(带hash) max-age=31536000(一年) 文件名变了就是新文件
图片 max-age=86400(一天) 图片更新不频繁
API数据 no-store 数据需要实时

表16:缓存策略最佳实践

面试经典问题:"如何更新用户的缓存?" 答案:给静态资源的文件名加 hash(如 app.a1b2c3.js)。文件内容变了,hash 就变了,URL 就变了,浏览器就会下载新版本。旧版本的 URL 还可以继续被缓存,不影响其他用户。


12. 跨域问题(CORS)

12.1 什么是跨域?

浏览器的同源策略(Same-Origin Policy)限制了不同源之间的资源访问。"同源"指的是协议+域名+端口完全相同。

URL 是否同源(相对 http://example.com:80 原因
http://example.com:80/api ✅ 同源 完全相同
https://example.com:80/api ❌ 跨域 协议不同
http://example.com:8080/api ❌ 跨域 端口不同
http://api.example.com/api ❌ 跨域 域名不同

表17:同源策略判断

12.2 CORS 的工作原理

CORS(Cross-Origin Resource Sharing)是解决跨域的标准方案。它通过 HTTP 头来告诉浏览器"这个跨域请求是允许的"。

简单请求 (GET/POST/HEAD + 简单Header):直接发,服务器在响应头中设置 Access-Control-Allow-Origin

复杂请求 (PUT/DELETE/自定义Header等):浏览器先发一个 OPTIONS 预检请求(Preflight),问服务器"我能不能发这个跨域请求?"。服务器返回允许的方法和 Header,然后浏览器才发真正的请求。

复制代码
# 预检请求
OPTIONS /api/users HTTP/1.1
Origin: http://frontend.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

# 预检响应
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://frontend.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400

13. HTTP 连接管理

13.1 短连接 vs 长连接

类型 说明 HTTP版本 效率
短连接 每个请求新建TCP连接,用完就关 HTTP/1.0默认
长连接 一个TCP连接复用多个请求 HTTP/1.1+默认

表18:短连接 vs 长连接

13.2 队头阻塞(Head-of-Line Blocking)

HTTP/1.1 的管线化问题: 虽然可以连续发多个请求,但响应必须按顺序返回。如果第一个请求的响应很慢,后面的都要排队等。

HTTP/2 的TCP层问题: 虽然应用层多路复用了,但TCP是字节流------一个TCP包丢了,所有流都要等重传。

HTTP/3 的解决方案: QUIC 在传输层支持真正的多路复用------每个流独立,一个流的丢包不影响其他流。

13.3 连接数限制

浏览器对同一域名的并发TCP连接数有限制(通常是6个)。这意味着如果你的页面需要请求100个资源,它们会分批进行------每批6个,等前6个完成后再发下一批。

优化手段:

  • 域名分片(Domain Sharding):把资源分散到多个子域名
  • HTTP/2 多路复用:一个连接搞定所有请求
  • 资源合并:把多个小文件合并成一个大文件(雪碧图、打包)

14. 从输入 URL 到页面渲染的全过程

这是面试中最经典的综合性问题。以下是完整流程:

第一步:URL 解析。 浏览器解析 URL,提取协议、域名、端口、路径、查询参数。

第二步:DNS 解析。 将域名解析为 IP 地址(浏览器缓存→系统缓存→本地DNS→递归查询)。

第三步:建立 TCP 连接。 三次握手建立 TCP 连接。如果是 HTTPS,还需要 TLS 握手。

第四步:发送 HTTP 请求。 浏览器构造 HTTP 请求报文(请求行+请求头+请求体),发送给服务器。

第五步:服务器处理请求。 服务器接收请求,经过路由、中间件、业务逻辑处理,生成响应。

第六步:返回 HTTP 响应。 服务器返回响应报文(状态行+响应头+响应体)。

第七步:浏览器解析 HTML。 构建 DOM 树。

第八步:浏览器解析 CSS。 构建 CSSOM 树。

第九步:构建渲染树。 DOM + CSSOM = Render Tree。

第十步:布局(Layout/Reflow)。 计算每个节点的位置和大小。

第十一步:绘制(Paint)。 将节点绘制到屏幕上。

第十二步:合成(Composite)。 将多个图层合成最终画面。

在这个过程中,还会遇到:

  • 遇到 <script> 标签:阻塞 HTML 解析(除非 async/defer)
  • 遇到 <link> 标签:不阻塞 HTML 解析,但阻塞渲染
  • 遇到图片:异步加载,不阻塞

15. 面试高频问题速查

Q1: GET 和 POST 的区别?

答: 语义不同(GET获取资源,POST提交数据)、幂等性不同(GET幂等,POST不幂等)、参数位置不同(URL vs Body)、缓存不同(GET可缓存,POST默认不缓存)、安全性不同(GET参数在URL中可见)。

Q2: HTTP/1.1 和 HTTP/2 的区别?

答: HTTP/2 引入了二进制分帧(替代文本格式)、多路复用(一个连接并行多个请求)、头部压缩(HPACK)、服务器推送。核心解决了HTTP/1.1的队头阻塞问题。

Q3: HTTPS 的握手过程?

答: TLS 1.3:ClientHello→ServerHello+证书+公钥→客户端验证证书+密钥交换→生成会话密钥→加密通信。1-RTT完成。

Q4: 三次握手为什么是三次?

答: 防止已失效的连接请求到达服务器导致资源浪费。两次握手无法确认客户端的连接意愿。

Q5: Cookie、Session、Token 的区别?

答: Cookie是客户端存储机制,Session是服务端存储机制,Token是无状态的身份凭证。Cookie有大小限制和安全风险,Session需要服务端存储,Token天然支持分布式。

Q6: HTTP 缓存机制?

答: 强缓存(Cache-Control/Expires,不问服务器直接用)+ 协商缓存(ETag/Last-Modified,问服务器变没变)。强缓存优先。

Q7: 什么是跨域?怎么解决?

答: 浏览器同源策略限制不同源的资源访问。解决方案:CORS(服务端设置Access-Control-Allow-Origin)、代理服务器、JSONP(仅GET)。

Q8: HTTP/3 为什么用 UDP?

答: TCP的队头阻塞在传输层无法解决。QUIC基于UDP,在传输层实现多路复用,一个流的丢包不影响其他流。同时QUIC内置加密和0-RTT建连。


16. 参考文献

1 Fielding, R., et al. (1999). "Hypertext Transfer Protocol -- HTTP/1.1". RFC 2616. IETF.

2 Belshe, M., Peon, R., & Thomson, M. (2015). "Hypertext Transfer Protocol Version 2 (HTTP/2)". RFC 7540. IETF.

3 Bishop, M. (2022). "HTTP/3". RFC 9114. IETF.

4 Rescorla, E. (2018). "The Transport Layer Security (TLS) Protocol Version 1.3". RFC 8446. IETF.

5 Fielding, R. T. (2000). "Architectural Styles and the Design of Network-based Software Architectures". Doctoral dissertation, University of California, Irvine.

6 Berners-Lee, T., Fielding, R., & Frystyk, H. (1996). "Hypertext Transfer Protocol -- HTTP/1.0". RFC 1945. IETF.

7 Mozilla. "HTTP | MDN Web Docs". https://developer.mozilla.org/en-US/docs/Web/HTTP.

8 Google. "HTTP/2 FAQ". https://developers.google.com/web/fundamentals/performance/http2.

9 Cloudflare. "What is HTTP/3?". https://www.cloudflare.com/learning/performance/what-is-http3/.

10 OWASP. "Cross-Site Scripting (XSS)". https://owasp.org/www-community/attacks/xss/.

相关推荐
Ivan CloudBay1 小时前
网站为什么会使用缓存?
服务器·网络·缓存·云服务器
复园电子2 小时前
USB Over IP技术详解:基于USB服务器实现USB设备远程访问、重定向与集中管理
服务器·网络协议·tcp/ip
TlSfoward2 小时前
TLSFoward 能帮你看到什么 TLSFOWARD抓包工具
服务器·爬虫·网络协议·https
懂好多的工业电源工程师3 小时前
F2424S-1WR3 适配优选 钡特电源 DF1-24S24LS|1W 工业24V转24V模块电源参数技术性能解析
网络·人工智能·电源模块
kaixin_learn_qt_ing3 小时前
单网卡绑定多个 IP 地址
网络·网络协议·tcp/ip
久久学姐4 小时前
Python开发爬虫的常用技术架构
爬虫·python·http·框架·数据存储
for_ever_love__4 小时前
iOS: 网络请求第三方库的使用: AFNetworking
网络·学习·ios·objective-c·cocoa·xcode
摇曳的精灵4 小时前
HTTP 与 MCP:不是替代,而是分层
网络·网络协议·http·mcp
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题 第214题】【10_网络协议篇】第5题:说一下 TCP 协议的三次握手和四次挥手
java·网络协议·tcp·三次握手·四次挥手