你可能已经在用 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 的原理,有助于你做出更好的网络架构决策。

延伸阅读


本文首发于 一个技术宅,欢迎关注获取更多网络协议和技术实战内容。