HTTP/1.0、1.1、2.0、3.0 有什么区别?
简化版
演进主线是不断解决「慢」和「队头阻塞」:1.0 每次请求都新建 TCP 连接(慢);1.1 默认长连接复用、但请求仍要排队(HTTP 层队头阻塞);2.0 二进制分帧 + 多路复用(一个连接并发多请求,解决 HTTP 队头阻塞)+ 头部压缩;3.0 换用基于 UDP 的 QUIC,解决了 HTTP/2 遗留的 TCP 层队头阻塞,还能更快建连。
详细版
HTTP/1.0:每个请求-响应都要新建并关闭一个 TCP 连接,握手开销大、慢。
HTTP/1.1(最经典、用了 20 年):
- 默认长连接(Keep-Alive):一个 TCP 连接复用于多个请求,省去重复握手;
- 管道化(pipelining):可以连续发多个请求不等响应,但响应必须按序返回,导致队头阻塞(前一个响应慢,后面全堵着),实际很少启用;
- 新增 Host 头(支持一台服务器托管多个域名)、分块传输编码、更完善的缓存控制。
HTTP/2.0:
- 二进制分帧:把报文拆成二进制帧传输,更高效;
- 多路复用(Multiplexing):一个 TCP 连接上多个请求/响应并发交错传输,彻底解决了 HTTP/1.1 的应用层队头阻塞;
- 头部压缩(HPACK):压缩重复的请求头,省流量;
- 服务器推送(Server Push):服务器可主动推送资源(实际使用少,已渐被弃用)。
HTTP/3.0:
- 底层从 TCP 换成 QUIC(基于 UDP,在用户态实现可靠传输);
- 解决了 HTTP/2 仍存在的 TCP 层队头阻塞(一个包丢了,TCP 会阻塞该连接上所有流);
- 建连更快(QUIC 把 TCP + TLS 握手合并,支持 0-RTT/1-RTT)、支持连接迁移(切换网络 IP 变了连接不断)。
完整版教学
一、一条主线:和「队头阻塞」死磕
HTTP 版本演进最好的记忆线索,是理解它一直在解决队头阻塞(Head-of-Line Blocking):
- 1.0 的问题:每个请求一个连接,握手开销大 → 1.1 用长连接解决;
- 1.1 的问题:一个连接上请求要排队,响应必须按序回,前面堵住后面(HTTP 层队头阻塞)→ 2.0 用多路复用解决;
- 2.0 的问题:多路复用是在一条 TCP 连接上做的,一旦某个 TCP 包丢了,TCP 为保证有序会阻塞整条连接上的所有流(TCP 层队头阻塞)→ 3.0 换 QUIC(基于 UDP)解决。
每一代都在解决上一代的队头阻塞——1.1 解决连接层面,2.0 解决 HTTP 层面,3.0 解决 TCP 层面。抓住这条线,四个版本的关系就清楚了。
二、HTTP/1.1 的长连接与管道化
- 长连接(Keep-Alive):1.1 默认开启。一个 TCP 连接处理完一个请求不立即关闭,继续复用给后续请求,省去反复三次握手。(注意别和 TCP keepalive 混,那是探活机制。)
- 管道化:允许不等前一个响应就发下一个请求,但服务器必须按请求顺序返回响应——如果第一个响应慢,后面的即使处理好了也得排队等。这个「按序返回」的限制就是 HTTP/1.1 队头阻塞的根源。因为问题多,浏览器基本默认不开管道化,转而用「同域名开多个 TCP 连接」来提升并发。
三、HTTP/2 的多路复用为什么高效
HTTP/2 把每个请求/响应拆成带流 ID 的二进制帧,多个流的帧可以在一条连接上交错发送,接收方按流 ID 重新组装。这样:
- 多个请求真正并发,不用像 1.1 那样排队或开多个连接;
- 解决了 HTTP 应用层的队头阻塞;
- 配合 HPACK 头部压缩,减少了重复请求头(如每次都带的 Cookie、User-Agent)的开销。
但它有个没解决的遗留问题——见下。
四、HTTP/3 为什么要抛弃 TCP
HTTP/2 的多路复用是在一条 TCP 连接上做的。TCP 为保证「有序、可靠」,一旦中间某个数据包丢了,它会阻塞后面所有数据直到丢包被重传补上——哪怕后面的数据属于别的、本来没问题的流。这就是 TCP 层队头阻塞:多路复用在 HTTP 层解决了,却被 TCP 层重新引入。
HTTP/3 的解法是换掉 TCP,用基于 UDP 的 QUIC:
- QUIC 在 UDP 上自己实现可靠传输,且各个流相互独立——一个流丢包不影响其他流,真正消除队头阻塞;
- QUIC 把传输握手和 TLS 握手合并,建连更快(1-RTT,恢复连接可 0-RTT);
- 支持连接迁移:手机从 WiFi 切到 4G,IP 变了,QUIC 用连接 ID 而非四元组标识连接,连接不中断。
五、常见误区
- ❌ 以为 HTTP/2 彻底解决了队头阻塞——它解决了 HTTP 层的,但 TCP 层的还在,HTTP/3 才解决。
- ❌ 以为 HTTP/1.1 不能复用连接——1.1 默认长连接(Keep-Alive),能复用。
- ❌ 把 HTTP Keep-Alive 和 TCP keepalive 混——前者是连接复用,后者是探活。
- ❌ 以为 HTTP/3 基于 TCP——它基于 UDP 上的 QUIC,正是为了摆脱 TCP 队头阻塞。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| HTTP/1.0 | 短连接为主 |
| HTTP/1.1 | 长连接、Host、缓存改进,但仍有队头阻塞 |
| HTTP/2 | 二进制分帧、多路复用、头部压缩 |
| HTTP/3 | 基于 QUIC/UDP,减少 TCP 队头阻塞 |
HTTP/1.1: one TCP connection, ordered responses
HTTP/2: multiple streams over one TCP
HTTP/3: QUIC streams over UDP
HTTP 版本演进主线是降低连接开销和队头阻塞,同时改善并发能力。
- 误区:HTTP/2 完全消除了队头阻塞。 HTTP/2 消除了应用层队头阻塞,但底层 TCP 丢包仍会阻塞所有流。
- 误区:HTTP/3 只是 HTTP/2 改名。 HTTP/3 基于 QUIC/UDP,传输层机制变化很大。
- 误区:HTTP/1.1 管道化被广泛使用。 管道化受响应顺序阻塞和兼容性影响,实际普及有限。
- 追问:HTTP/2 多路复用为什么高效? 多个 stream 在一个连接上交错发送帧,不必为每个请求建立连接。
- 追问:HPACK/QPACK 解决什么? 压缩重复请求头,减少 header 传输开销。
- 追问:为什么 HTTP/3 更抗丢包? QUIC 在传输层支持独立 stream,某个流丢包不必阻塞其他流的数据交付。
七、加强记忆
演进就是和队头阻塞死磕:1.0 短连接慢 → 1.1 默认长连接但响应按序回有 HTTP 层队头阻塞 → 2.0 二进制分帧 + 多路复用(解决 HTTP 层队头阻塞)+ 头部压缩 → 3.0 基于 UDP 的 QUIC,解决 TCP 层队头阻塞、握手更快、支持连接迁移。每一代解决上一代的队头阻塞。