# HTTP/3 总览

> TCP 队头阻塞为什么无法在 TCP 上解决，以及 h3 = HTTP/2 语义 + QUIC 传输。

- 作者：David（道雾轩）
- 专栏：HTTP/2 与 HTTP/3 协议详解（https://daiw.org/manual/http2-3.md）
- 最后更新：2026-07-26
- 原文：https://daiw.org/manual/http2-3/h3-overview
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

## 唯一的动机

HTTP/2 消除了 HTTP 层的队头阻塞，但**所有流仍共享一条 TCP 连接**：

```text
TCP 是一条有序字节流。内核的契约是:
「按发送顺序、无缺口地把字节交给应用」

  发送: [流1-A][流3-B][流1-C][流5-D]
                ↑ 丢失
  接收: 流1-A 已交付
        流3-B 丢了 → 内核必须等重传
        流1-C、流5-D 已完整到达，但被扣在内核缓冲区
        → 三个流一起卡住，等一个与它们无关的包
```

**根源在于 TCP 不知道流的存在**。它只看到一条字节流，缺口就是缺口。这一点**无法在 TCP 之上修复**——无论 HTTP 层怎么设计，都改变不了内核的交付语义。

要解决，只能换传输层：让传输层**自己知道有多个独立的流**，某个流丢包时不影响其他流的交付。这就是 QUIC，也是 HTTP/3 存在的全部理由。

## 为什么不改 TCP

理论上可以给 TCP 加多流支持（SCTP 就是这么做的），实际不可行：

| 障碍 | 说明 |
| --- | --- |
| **中间件僵化（ossification）** | 全球的 NAT、防火墙、负载均衡器只认识 TCP/UDP。新传输协议号的包会被大量丢弃 |
| **内核部署周期** | TCP 实现在操作系统内核里，一个改动要等数年才能覆盖大多数设备 |
| **TCP 头部明文** | 中间件会窥探甚至改写 TCP 选项，导致新特性被破坏 |

QUIC 的对策：

- **跑在 UDP 上** —— UDP 到处都通，无需中间件升级。
- **实现在用户态** —— 随浏览器/服务端软件更新，迭代周期从年降到周。
- **几乎全部加密** —— 连包序号和大部分头部都加密，中间件**看不到也改不了**，从根上防止再次僵化。

## HTTP/3 = HTTP/2 语义 + QUIC

分层对比：

```text
HTTP/1.1        HTTP/2          HTTP/3
─────────────────────────────────────────
HTTP 语义       HTTP 语义        HTTP 语义      ← 三版完全相同 (RFC 9110)
─────────────────────────────────────────
文本报文        二进制帧         二进制帧        ← h3 帧格式与 h2 相似但不同
                HPACK           QPACK          ← 为乱序交付重新设计
                流/多路复用      ↓ 下沉到 QUIC
                流量控制         ↓ 下沉到 QUIC
─────────────────────────────────────────
TLS (可选)      TLS (事实必需)   ↓ 内建于 QUIC
─────────────────────────────────────────
TCP             TCP             QUIC
                                UDP
```

**HTTP/3 把 h2 的三样东西下沉到了传输层**：流的多路复用、流量控制、连接管理（部分）。h3 自己只剩下「帧格式 + 字段压缩 + HTTP 语义映射」。

结果是 h3 规范（RFC 9114）比 h2 规范**短得多**——重活都交给了 QUIC。

## 相对 h2 的改进清单

| 改进 | 说明 |
| --- | --- |
| **消除传输层队头阻塞** | 一个流丢包只阻塞该流，其他流照常交付 |
| **握手更快** | TCP+TLS1.3 需 2–3 RTT；QUIC **1 RTT**，会话恢复 **0 RTT** |
| **连接迁移** | 用 Connection ID 而非四元组标识连接，**换 IP/网络不断连**（WiFi 切 4G 无感） |
| **更好的丢包恢复** | 单调递增包号消除 TCP 的重传歧义；用户态可用更先进的拥塞控制 |
| **强制加密** | 传输层元数据也加密，抗窥探与抗僵化 |
| **无 CONTINUATION 阻塞** | 帧结构简化，字段块无需连续独占连接 |

## 代价

诚实地列出来：

1. **CPU 开销更高**。UDP 的内核路径优化远不如 TCP（无 GSO/GRO 硬件卸载的历史积累），加解密也在用户态。实测 h3 的 CPU 消耗常为 h2 的 **2–3 倍**，虽在快速改善。
2. **UDP 可能被封禁或限速**。部分企业网络与运营商对 UDP 有限制，客户端**必须**保留回落到 h2/1.1 的能力。
3. **实现成熟度**。QUIC 栈自己实现了拥塞控制、丢包恢复、加密——这些在 TCP 里是内核数十年打磨的成果。
4. **可观测性下降**。传输层加密后，运维再也不能靠抓包分析 RTT、重传、窗口——排障需依赖端点自己导出的 qlog。

## 版本标识与发现

- ALPN 标识：**`h3`**。
- 因为客户端无法预知服务端是否支持 UDP/QUIC，h3 **必须先被发现**——通过 [`Alt-Svc` 字段或 DNS HTTPS 记录](https://daiw.org/manual/http2-3/h3-connection)。
- 首次访问几乎总是走 h2/1.1，随后才升级到 h3。

下一篇：[QUIC 传输层](https://daiw.org/manual/http2-3/quic-transport)。
