图解 QUIC 协议:为什么它比 TCP 快
你可能已经在用 QUIC 了,只是你不知道。
打开 Chrome 浏览器,访问 Google、YouTube、Cloudflare 托管的任意网站——底层传输协议很可能已经是 QUIC 而不是 TCP。
但 QUIC 到底是什么?它凭什么比用了几十年的 TCP 还快?今天用图解的方式,把 QUIC 的核心原理讲清楚。
TCP 的三个痛点
在理解 QUIC 之前,先看 TCP 在现代互联网中暴露出的三个核心问题。
如果你对 TCP 的性能问题感兴趣,推荐先看这篇:为什么 TCP 协议有性能问题
痛点 1:握手太慢
TCP 建立连接需要三次握手(1.5 RTT),如果加上 TLS 1.2 的握手,总共需要 3 个 RTT 才能开始传数据:
客户端 服务器
|--- SYN ------------>| ← TCP 第 1 次
|<--- SYN+ACK --------| ← TCP 第 2 次
|--- ACK ------------>| ← TCP 第 3 次
|--- ClientHello ---->| ← TLS 第 1 次
|<--- ServerHello ----| ← TLS 第 2 次
|--- Finished ------->| ← TLS 第 3 次
|<--- Finished --------| ← TLS 第 4 次
|--- 数据 ------------>| ← 终于可以发数据了!
3 个 RTT,如果服务器在美国,客户端在中国,光速往返延迟约 200ms,光握手就要 600ms。
痛点 2:队头阻塞
TCP 是字节流协议,严格保序。如果一个包丢了,后面所有包都得等它重传完成才能交给应用层,即使后面的包属于完全不同的 HTTP 请求。
请求 A 的包:[1] [2] [丢失] [4] [5]
请求 B 的包: [6] [7] [8] ← 全部被阻塞!
HTTP/2 虽然在应用层实现了多路复用,但底层还是一条 TCP 连接,队头阻塞问题依然存在。
痛点 3:连接不可迁移
TCP 连接用四元组(源 IP、源端口、目标 IP、目标端口)标识。手机从 Wi-Fi 切换到 4G,IP 变了,TCP 连接直接断开,需要重新握手。
QUIC 如何解决这三个问题
QUIC(Quick UDP Internet Connections)基于 UDP 构建,从协议层面解决了上述三个痛点。
解决方案 1:0-RTT 握手
QUIC 把传输层握手和加密握手合并为一步,首次连接只需 1 个 RTT,重连甚至可以 0-RTT:
【首次连接:1 RTT】
客户端 服务器
|--- Initial --------->| ← 同时发送加密参数 + 数据
|<--- Handshake -------| ← 返回证书 + 密钥
|--- 数据 ------------->| ← 1 RTT 后开始传数据
【重连:0 RTT】
客户端 服务器
|--- 数据 + 缓存凭证 -->| ← 直接发数据!
|<--- 数据 -------------|
原理:QUIC 使用 TLS 1.3,客户端缓存上次连接的加密参数,重连时直接用缓存凭证加密数据,不需要额外握手。
比 TCP + TLS 1.2 快了 2 个 RTT,在高延迟网络下体感非常明显。
解决方案 2:流级别多路复用
QUIC 在传输层原生支持多路复用,每个 HTTP 请求对应一个独立的 Stream,Stream 之间互不阻塞:
QUIC 连接
├── Stream 1(请求 A):[1] [2] [丢失] [4] [5] ← 只阻塞 Stream 1
├── Stream 2(请求 B):[6] [7] [8] ← 正常接收!不受影响
└── Stream 3(请求 C):[9] [10] ← 正常接收!
关键区别:TCP 的队头阻塞发生在连接级别,QUIC 的丢包只影响单个 Stream。其他 Stream 的数据可以立即交给应用层。
解决方案 3:连接 ID 迁移
QUIC 不用四元组标识连接,而是用一个 Connection ID:
【Wi-Fi → 4G 切换】
TCP:
Wi-Fi: 192.168.1.100:12345 → 1.2.3.4:443 ← 连接 A
4G: 10.0.0.50:23456 → 1.2.3.4:443 ← 连接 B(新连接!重新握手)
QUIC:
Wi-Fi: 192.168.1.100:12345 → 1.2.3.4:443 Connection ID: abc123
4G: 10.0.0.50:23456 → 1.2.3.4:443 Connection ID: abc123 ← 同一连接!
IP 和端口变了,但 Connection ID 没变,服务器认为是同一个连接,无缝继续传数据。用户在地铁里切换基站时,视频不会卡顿。
QUIC 的协议栈对比
传统方案: QUIC 方案:
┌─────────────┐ ┌─────────────┐
│ HTTP/2 │ │ HTTP/3 │
├─────────────┤ ├─────────────┤
│ TLS 1.2 │ │ QUIC │
├─────────────┤ │ (含 TLS 1.3) │
│ TCP │ ├─────────────┤
├─────────────┤ │ UDP │
│ IP │ ├─────────────┤
└─────────────┘ │ IP │
└─────────────┘
QUIC 把 TCP 和 TLS 的功能合并到一层,减少了协议栈层次,也减少了不同层之间的沟通开销。
实际验证:抓包看 QUIC
用 Chrome 访问 https://www.google.com,打开 chrome://net-internals/#quic 可以看到 QUIC 连接信息。
或者用 curl 测试(需要 HTTP/3 支持):
# 安装支持 HTTP/3 的 curl(macOS)
brew install curl
# 测试 QUIC 连接
curl --http3 -I https://www.cloudflare.com
# 如果响应头包含 alt-svc: h3="..." 说明支持 QUIC
用 Wireshark 抓包可以看到:QUIC 的数据包跑在 UDP 443 端口上,包内容是加密的(TLS 1.3),只有 Initial 包的头部是明文。
QUIC 的代价
QUIC 不是万能的,它也有一些取舍:
1. CPU 开销更高
QUIC 在用户态实现(不像 TCP 在内核态),加解密、拥塞控制都需要 CPU 处理。对于高吞吐服务器,CPU 消耗比 TCP 高 10-20%。
2. UDP 可能被运营商限速
部分网络设备对 UDP 流量有限速策略,QUIC 可能被误伤。不过随着 QUIC 普及,这个问题在逐步改善。
3. 生态还在成熟
TCP 经过几十年优化,各操作系统内核都有高度优化的实现。QUIC 的实现库(如 quiche、msquic)还在快速迭代中。
总结
| 特性 | TCP + TLS 1.2 | QUIC |
|---|---|---|
| 首次握手 | 3 RTT | 1 RTT |
| 重连握手 | 1-2 RTT | 0 RTT |
| 队头阻塞 | 连接级别 | Stream 级别 |
| 网络切换 | 连接断开 | 无缝迁移 |
| 加密 | 可选 | 强制(TLS 1.3) |
| 协议层 | 内核态 | 用户态 |
QUIC 已经是 HTTP/3 的底层传输协议,Google、Cloudflare、Facebook 等大厂已经大规模部署。了解 QUIC 的原理,有助于你做出更好的网络架构决策。
延伸阅读
- 为什么 TCP 协议有性能问题 — 深入理解 TCP 的设计局限
- 从零编写基于 UDP 的通信程序 — 动手理解 UDP 编程
本文首发于 一个技术宅,欢迎关注获取更多网络协议和技术实战内容。




