本文最后更新于209 天前,其中的信息可能已经过时,如有错误请发送邮件到1986413837@qq.com
一、HTTP/1.1 长连接与它的困境
HTTP/1.1 的核心优化是引入了长连接(Persistent Connection)通过复用 TCP 连接解决了 HTTP/1.0 中频繁建立/关闭连接的开销
1. 长连接原理
- 机制 客户端发送请求时 在请求头中省略或包含
Connection: Keep-Alive(现在已是默认) - 效益 一次网页加载中的所有资源(HTML CSS 图片等)都可以在同一个 TCP 连接上传输
- 解决的问题 避免了每次请求的 3 次 握手延迟和 4 次 挥手延迟
2. 队头阻塞(HOL Blocking)的起源
- 原理 HTTP/1.1 引入了管道化(Pipelining)允许客户端连续发送请求 R1 R2 R3 而不必等待响应 S1
- 问题 服务器必须严格按照请求的接收顺序(R1 接着 R2 接着 R3)发送响应(S1 接着 S2 接着 S3)
- 后果 如果请求 R2 因为服务器处理时间长而延迟 那么即使 R3 已经准备好响应 S3 它也必须等待 S2 先发送 这就是 HTTP 协议层面的 HOL 阻塞
- 应对措施 浏览器通常会打开 4 到 8 个并行的 TCP 连接 来绕过这个单连接的阻塞问题 但这又增加了 TCP 连接管理的开销
二、HTTP/2 二进制分帧与多路复用
HTTP/2 旨在彻底解决 HTTP/1.1 的应用层 HOL 阻塞 它的核心是引入了二进制分帧层(Binary Framing Layer)
1. 二进制分帧层原理
- 机制 在应用层(HTTP)和传输层(TCP)之间增加一个分帧层 HTTP/2 将所有请求 响应 头部 数据都拆分成更小的 带有流标识符 (Stream ID) 的帧 (Frames)
- 流 (Stream) 一个完整的请求或响应被称为一个流 每个流都有一个唯一的 ID
- 多路复用 (Multiplexing) 原理
- 所有流的帧都通过同一个 TCP 连接交错发送
- 客户端和服务器根据帧上的 Stream ID 将分散的帧重新组装成完整的请求和响应
- 解决的问题 由于帧是交错传输的 如果流 A 的一个帧被延迟 其他流 B C 的帧仍然可以继续传输 彻底解决了 HTTP/1.1 协议层面的 HOL 阻塞
2. 遗留的问题 TCP 传输层 HOL 阻塞
- 原理 尽管 HTTP/2 在应用层解决了 HOL 阻塞 但它仍然建立在 TCP 协议之上 TCP 是一个有序 可靠的字节流协议
- 后果 如果在 TCP 连接上传输的一个数据包(Packet)丢失 TCP 必须重传并等待这个丢失的包到达 保证有序性 在此期间 即使这个包后面的数据包已经到达接收端 TCP 也不能将其交付给上层(HTTP/2)
- 结论 HTTP/2 将性能瓶颈从应用层转移到了传输层 (TCP)
三、HTTP/3 基于 UDP 的 QUIC 协议
HTTP/3 的设计目标就是消除 TCP 带来的 HOL 阻塞 它通过将底层传输协议替换为 **QUIC(Quick UDP Internet Connections)**来实现
1. QUIC 协议原理
- 基础 QUIC 运行在不可靠的 UDP 协议之上 但它在应用层实现了 TCP 提供的可靠性 拥塞控制和流量控制等功能
- 独立流(Independent Streams) QUIC 引入了多条相互独立的流 类似 HTTP/2 的流 但它是在 QUIC 层而非 TCP 层实现的
- 彻底解决 HOL 阻塞原理
- QUIC 流之间是相互独立的 如果流 A 上的一个 UDP 包丢失 只有流 A 上的数据传输会暂停等待重传
- 流 B C 上的数据可以继续正常传输并交付给上层应用
- 这是对 TCP 最大的突破 彻底消除了传输层 HOL 阻塞
2. 关键优化 更快的连接建立
- 机制 QUIC 将 TCP 的握手(3次 往返)和 TLS 的加密握手(2次 往返)合并在一起
- 效益
- 首次连接 通常只需 1次 往返时间 (1-RTT) 即可完成加密和连接的建立
- 重复连接 利用缓存的会话信息 可以实现 0次 往返时间 (0-RTT) 握手 客户端可以直接发送加密数据
- 解决的问题 大幅减少了建立安全连接所需的延迟
总结对比图
| 机制 | HTTP/1.1 | HTTP/2 | HTTP/3 (QUIC) |
| 底层协议 | TCP | TCP | UDP |
| 应用层 HOL | 存在(单连接顺序响应) | 解决(多路复用) | 解决(多流独立) |
| 传输层 HOL | 存在(TCP 数据包丢失) | 存在(TCP 数据包丢失) | 解决(QUIC 流独立重传) |
| 连接建立时延 | 3次 RTT | 5次 RTT (TCP + TLS) | 1次 RTT 或 0次 RTT |