HTTP/HTTPS 协议演进
HTTP 版本演进
Section titled “HTTP 版本演进”HTTP 1.0:短连接时代
Section titled “HTTP 1.0:短连接时代”每个请求都需要建立新的 TCP 连接,请求完成后立即关闭。
问题: 每个请求 = 三次握手 + 请求/响应 + 四次挥手 一个网页有 100 个资源 → 100 次 TCP 连接建立/释放 → 延迟极高HTTP 1.1:持久连接
Section titled “HTTP 1.1:持久连接”关键改进:
- 持久连接(Keep-Alive):默认启用,同一 TCP 连接可发多个请求,
Connection: keep-alive - 管道化(Pipelining):允许在收到响应前发送下一个请求(理论上)
- 分块传输(Chunked Transfer Encoding):不需要预先知道响应体大小
- Host 头:支持虚拟主机(同一 IP 多个域名)
- 缓存控制:Cache-Control、ETag/If-None-Match、Last-Modified/If-Modified-Since
遗留问题:
队头阻塞(Head-of-Line Blocking): 虽然管道化允许发送多个请求,但响应必须按请求顺序返回 如果第一个请求处理慢,后续请求的响应被阻塞 → 浏览器通常为同一域名打开 6 个并行 TCP 连接来绕过此限制HTTP 2.0:多路复用
Section titled “HTTP 2.0:多路复用”核心改进:
1. 二进制分帧(Binary Framing) HTTP 1.x 是文本协议,HTTP/2 将消息分割为二进制帧(Frame) 帧类型:HEADERS、DATA、SETTINGS、RST_STREAM、PUSH_PROMISE 等
2. 多路复用(Multiplexing)★★★ 在单个 TCP 连接上并发传输多个请求/响应 每个请求/响应对应一个流(Stream),流有独立 ID 帧可以交错发送,接收方按 Stream ID 重组
HTTP 1.1:请求1 → 等响应1 → 请求2 → 等响应2 HTTP 2.0:请求1 ┐ ┌ 响应1 请求2 ┤→ 单个TCP连接 →├ 响应3(先完成) 请求3 ┘ └ 响应2
3. 头部压缩(HPACK) HTTP 头部在请求间有大量重复(Cookie、User-Agent 等) HPACK 算法:维护动态表,用索引引用已发送的头部字段 压缩率可达 80-90%
4. 服务端推送(Server Push) 服务端可主动推送客户端尚未请求的资源 如:请求 HTML,服务端主动推送 CSS/JS(浏览器未来可能会移除此特性)
5. 流优先级(Stream Priority) 客户端可设置流的权重和依赖关系,让重要资源优先传输HTTP 2.0 的问题:TCP 层面的队头阻塞仍然存在。一个 TCP 包丢失会导致所有流的所有帧等待重传。
HTTP 3.0:QUIC 协议
Section titled “HTTP 3.0:QUIC 协议”HTTP 3.0 不再使用 TCP,改用 QUIC(Quick UDP Internet Connections)QUIC 基于 UDP,在应用层实现了可靠传输
核心优势:1. 彻底解决队头阻塞 QUIC 的流是完全独立的,一个流的丢包不影响其他流
2. 0-RTT / 1-RTT 连接建立 首次连接:1-RTT(QUIC 握手包含 TLS 1.3 握手) 恢复连接:0-RTT(使用缓存的会话密钥,直接发数据) 对比 TCP + TLS 1.2:需要 3-RTT(TCP 握手 + TLS 握手)
3. 连接迁移(Connection Migration) 用连接 ID 标识连接,而非 IP:Port 切换网络(如 WiFi → 4G)不需要重建连接
4. 无中间件僵化(Ossification)问题 QUIC 包完全加密,中间路由器无法解析修改,便于协议升级HTTPS:HTTP + TLS
Section titled “HTTPS:HTTP + TLS”TLS 握手流程(TLS 1.2)
Section titled “TLS 握手流程(TLS 1.2)”客户端 服务端 │ │ │── ClientHello ─────────────────────────► │ │ (TLS版本, 支持的加密套件, 随机数Client-Random) │ │ │ ◄──────────────────────────── ServerHello│ │ (选定的加密套件, 随机数Server-Random) │ │ ◄─────────────────────────────Certificate│ │ (服务端证书,含公钥) │ │ ◄──────────────── ServerKeyExchange(可选) │ │ (ECDHE参数等) │ │ ◄─────────────────────────── ServerHelloDone │ │ │── ClientKeyExchange ───────────────────► │ │ (发送 Pre-Master Secret,用服务端公钥加密)│ │── ChangeCipherSpec ─────────────────────►│ │── Finished ─────────────────────────────►│ │ (用协商好的密钥加密的握手摘要) │ │ │ │ ◄──────────────────────── ChangeCipherSpec│ │ ◄──────────────────────────────── Finished│ │ │ └──────── 加密通信开始(对称加密)────────────┘
密钥派生: Master Secret = PRF(Pre-Master Secret, Client-Random, Server-Random) → 从 Master Secret 派生出: client write key / server write key(对称加密密钥) client write MAC key / server write MAC key(消息认证密钥) client write IV / server write IV(初始向量)TLS 1.3 的改进
Section titled “TLS 1.3 的改进”TLS 1.2:2-RTT(ClientHello → ServerHello+Cert+Done → ClientKeyExchange+Finished → Finished)
TLS 1.3:1-RTT 1. 移除了 RSA 密钥交换(只保留 ECDHE,支持前向保密) 2. ClientHello 中直接携带密钥协商参数(key_share),服务端收到后立即派生密钥 3. 移除了不安全的加密套件(RC4、DES、3DES、MD5、SHA-1) 4. 0-RTT 恢复(Session Resumption with Early Data): 使用 PSK(Pre-Shared Key),客户端可在第一个包中携带加密应用数据 注意:0-RTT 数据不具备前向保密性,且易受重放攻击,应用场景需谨慎证书链与信任验证
Section titled “证书链与信任验证”证书链(Chain of Trust):
根 CA 证书(Root CA)← 内置于操作系统/浏览器,自签名,高度可信 └── 中间 CA 证书(Intermediate CA)← 由根 CA 签发 └── 服务器证书(End Entity)← 由中间 CA 签发,含域名和公钥
验证流程: 1. 浏览器收到服务器证书 2. 读取签发者(Issuer)字段,找到中间 CA 证书(服务器通常一并发送) 3. 用中间 CA 的公钥验证服务器证书的签名 4. 再向上,用根 CA 的公钥验证中间 CA 证书的签名 5. 根 CA 证书在本地受信任列表中 → 验证通过 6. 检查证书有效期、域名、CRL/OCSP(是否被吊销)HTTPS 防中间人攻击(MITM)的关键:证书必须由受信任 CA 签发,攻击者无法伪造合法证书(除非 CA 被攻破或用户安装了恶意根证书)。
HTTP 缓存机制
Section titled “HTTP 缓存机制”强缓存(不发请求,直接用本地缓存): Cache-Control: max-age=3600 ← 优先级更高 Expires: Wed, 21 Oct 2023 ... ← HTTP 1.0 时代,受客户端时间影响
协商缓存(发请求询问服务端缓存是否有效): ETag / If-None-Match ← 基于内容指纹(哈希),优先级更高 Last-Modified / If-Modified-Since ← 基于最后修改时间(精度到秒)
流程: 第一次请求 → 服务端返回 200 + 资源 + ETag + Cache-Control 第二次请求(max-age 未过期)→ 直接使用本地缓存(200 from cache / 200 from disk cache) 第二次请求(max-age 已过期)→ 携带 If-None-Match: <ETag值> 发给服务端 ├── 资源未变 → 服务端返回 304 Not Modified(无响应体,节省带宽) └── 资源已变 → 服务端返回 200 + 新资源 + 新ETag常见 HTTP 状态码
Section titled “常见 HTTP 状态码”| 状态码 | 含义 | 说明 |
|---|---|---|
| 200 | OK | 请求成功 |
| 201 | Created | 资源创建成功(POST/PUT) |
| 204 | No Content | 成功但无响应体(DELETE) |
| 301 | Moved Permanently | 永久重定向,浏览器缓存新地址 |
| 302 | Found | 临时重定向,不缓存 |
| 304 | Not Modified | 协商缓存命中,使用本地缓存 |
| 400 | Bad Request | 请求格式错误 |
| 401 | Unauthorized | 未认证(需要登录) |
| 403 | Forbidden | 已认证但无权限 |
| 404 | Not Found | 资源不存在 |
| 405 | Method Not Allowed | 请求方法不支持 |
| 429 | Too Many Requests | 限流 |
| 500 | Internal Server Error | 服务端内部错误 |
| 502 | Bad Gateway | 网关收到上游无效响应(如 Nginx 转发失败) |
| 503 | Service Unavailable | 服务不可用(如过载、维护) |
| 504 | Gateway Timeout | 网关等待上游超时 |
WebSocket
Section titled “WebSocket”WebSocket 是基于 TCP 的全双工通信协议,通过 HTTP 握手升级建立。
升级握手: GET /chat HTTP/1.1 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== ← 随机 base64 Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= ← SHA1(Key + GUID)
建立后: • 不再是 HTTP,使用 WebSocket 帧格式 • 全双工:服务端可主动推送,无需轮询 • 适合场景:实时聊天、实时数据推送、在线游戏、协同编辑WebSocket vs SSE vs 长轮询:
| 方式 | 全双工 | 服务端推送 | 适用场景 |
|---|---|---|---|
| 长轮询 | 否 | 模拟 | 简单通知,实现简单 |
| SSE | 否(单向) | 是 | 服务端推送流数据(日志、股票) |
| WebSocket | 是 | 是 | 双向实时通信(聊天、游戏) |
Q:HTTP 2.0 相比 1.1 的主要改进是什么?
多路复用(单连接并发多请求,解决 HTTP 层面的队头阻塞)、二进制分帧(解析效率高)、头部压缩(HPACK,减少重复头部传输)、服务端推送(主动推送资源)。
Q:HTTPS 如何防止中间人攻击?
通过 CA 证书体系。服务端证书由受信任 CA 签发,包含服务端公钥和域名信息。中间人无法伪造合法的 CA 签名证书(私钥未泄露的前提下),浏览器验证证书有效性和域名匹配后才建立加密连接。
Q:HTTP 的缓存机制是怎样的?
分强缓存和协商缓存。强缓存(Cache-Control: max-age)未过期时直接使用本地缓存,不发请求。过期后发送协商请求(携带 ETag 或 Last-Modified),服务端判断资源未变则返回 304(节省带宽),已变则返回 200 和新资源。
Q:301 和 302 的区别?
301 是永久重定向,浏览器会缓存新地址,后续直接访问新地址不再请求原地址;302 是临时重定向,每次都会请求原地址再跳转。SEO 场景中,301 能传递页面权重,302 不能。
Q:HTTP 3.0 为什么使用 UDP?
HTTP 2.0 虽然解决了 HTTP 层面的队头阻塞,但 TCP 层面的队头阻塞依然存在(一个 TCP 包丢失阻塞所有流)。QUIC 基于 UDP,在应用层实现了独立的流,一个流的丢包不影响其他流,同时支持 0-RTT 快速连接建立和连接迁移。