QUIC 协议
Abstract |
QUIC protocol |
Authors |
Walter Fan |
Status |
v1.0 |
Updated |
2026-03-20 |
概述
QUIC (Quick UDP Internet Connections) 是一种基于 UDP 的多路复用安全传输协议,由 Google 最初设计,后经 IETF 标准化为 RFC 9000。QUIC 提供了与 TCP+TLS 等效的功能,但具有更低的连接建立延迟、更好的多路复用支持和内置的连接迁移能力。
QUIC 的核心设计目标:
低延迟连接建立: 1-RTT 握手(首次连接),0-RTT 恢复(后续连接)
多路复用无队头阻塞: 多个流独立传输,单个流的丢包不影响其他流
内置加密: 所有 QUIC 数据包都经过加密,使用 TLS 1.3
连接迁移: 基于 Connection ID 而非 IP:Port 四元组标识连接
改进的丢包检测和拥塞控制: 更精确的 RTT 测量和灵活的拥塞控制
QUIC 在 WebRTC 生态系统中的地位日益重要,WebTransport 和 Media over QUIC (MoQ) 等新技术正在探索使用 QUIC 作为实时媒体传输的替代方案。
背景
HTTP/2 通过多路复用和头部压缩显著提升了 Web 性能,但它仍然受限于 TCP 的固有问题。虽然 HTTP/2 允许在单个 TCP 连接上多路复用多个流,但当某个流发生丢包时,TCP 的可靠传输机制会阻塞整个连接上的所有流——这就是 TCP 层面的队头阻塞 (Head-of-Line Blocking)。
Daniel Stenberg 在其关于 HTTP/3 的著作中指出,在 2% 丢包率的情况下,使用 HTTP/1 的六个并行连接反而比 HTTP/2 的单连接多路复用性能更好。
QUIC 通过在 UDP 之上实现传输层功能来解决这个问题:
多路复用的流之间相互独立,单个流的丢包不影响其他流
连接建立与 TLS 握手合并,减少了 RTT
在用户空间实现,可以快速迭代和部署
Google Cloud Platform 在 2018 年为其负载均衡器引入 QUIC 支持后,全球平均页面加载时间改善了 8%,在高延迟地区改善高达 13%。
QUIC 与 TCP 对比
特性 |
TCP |
QUIC |
|---|---|---|
传输层 |
内核实现 |
用户空间实现(基于 UDP) |
连接建立 |
TCP 3-way handshake + TLS 握手 (2-3 RTT) |
1-RTT(含 TLS 1.3),0-RTT 恢复 |
加密 |
可选(TLS 层) |
强制(内置 TLS 1.3) |
多路复用 |
无原生支持(HTTP/2 在应用层实现) |
原生流多路复用,无队头阻塞 |
队头阻塞 |
存在(丢包阻塞所有流) |
仅影响丢包的流 |
连接迁移 |
不支持(IP 变化需重建连接) |
支持(基于 Connection ID) |
拥塞控制 |
内核实现,更新缓慢 |
用户空间实现,可插拔 |
NAT 重绑定 |
连接中断 |
通过 Connection ID 保持连接 |
协议僵化 |
严重(中间设备依赖 TCP 头部) |
头部加密,防止中间设备干预 |
QUIC 核心特性
流多路复用 (Stream Multiplexing)
QUIC 的流 (stream) 是协议的基本服务抽象。每个流是一个有序的字节序列,流之间相互独立。
QUIC 连接
├── Stream 0 (双向): 控制流
├── Stream 1 (客户端发起,双向): HTTP 请求/响应 1
├── Stream 3 (客户端发起,双向): HTTP 请求/响应 2
├── Stream 5 (客户端发起,双向): HTTP 请求/响应 3
├── Stream 2 (服务器发起,双向): 服务器推送
└── Stream 7 (客户端发起,单向): 单向数据
流的类型由 Stream ID 的低 2 位决定:
+------+------------------------------------------+
| 低2位 | 流类型 |
+------+------------------------------------------+
| 0x00 | 客户端发起的双向流 (Client-Initiated, |
| | Bidirectional) |
+------+------------------------------------------+
| 0x01 | 服务器发起的双向流 (Server-Initiated, |
| | Bidirectional) |
+------+------------------------------------------+
| 0x02 | 客户端发起的单向流 (Client-Initiated, |
| | Unidirectional) |
+------+------------------------------------------+
| 0x03 | 服务器发起的单向流 (Server-Initiated, |
| | Unidirectional) |
+------+------------------------------------------+
关键优势:当 Stream 3 发生丢包时,只有 Stream 3 的数据传输被阻塞,Stream 1 和 Stream 5 可以继续正常接收和处理数据。
连接迁移 (Connection Migration)
QUIC 使用 Connection ID 而非传统的四元组 (源IP, 源端口, 目标IP, 目标端口) 来标识连接。这使得当客户端的网络地址发生变化时(如从 Wi-Fi 切换到蜂窝网络),连接可以无缝迁移。
场景: 用户从 Wi-Fi 切换到 4G
TCP 行为:
Wi-Fi: 192.168.1.100:5000 → 服务器 [连接 A]
切换到 4G...
4G: 10.0.0.50:6000 → 服务器 [需要新建连接 B]
(之前的连接 A 中断,需要重新握手)
QUIC 行为:
Wi-Fi: 192.168.1.100:5000 → 服务器 [Connection ID: 0xABCD]
切换到 4G...
4G: 10.0.0.50:6000 → 服务器 [Connection ID: 0xABCD]
(同一个连接,通过路径验证后继续传输)
连接迁移过程中,QUIC 会进行路径验证 (Path Validation),确保新路径的可达性和安全性。
握手与加密
QUIC 将传输层握手和 TLS 1.3 握手合并,实现了高效的连接建立:
1-RTT 握手(首次连接)
Client Server
Initial[0]: CRYPTO[CH] -------->
Initial[0]: CRYPTO[SH]
Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
<--------
Handshake[0]: CRYPTO[FIN] -------->
1-RTT[0]: STREAM[0, ...] -------->
<-------- 1-RTT[1]: STREAM[1, ...]
CH = ClientHello, SH = ServerHello
EE = EncryptedExtensions, CERT = Certificate
CV = CertificateVerify, FIN = Finished
0-RTT 恢复(后续连接)
Client Server
Initial[0]: CRYPTO[CH]
0-RTT[0]: STREAM[0, ...] -------->
Initial[0]: CRYPTO[SH]
Handshake[0]: CRYPTO[EE, FIN]
<--------
Handshake[0]: CRYPTO[FIN] -------->
1-RTT[1]: STREAM[1, ...] -------->
<-------- 1-RTT[0]: STREAM[0, ...]
0-RTT 数据在第一个数据包中就可以发送,但需要注意重放攻击的风险。
QUIC 使用多层加密保护:
Initial packets: 使用从 Connection ID 派生的密钥(公开的,仅防止意外修改)
Handshake packets: 使用握手密钥
1-RTT packets: 使用应用数据密钥
Header protection: 数据包头部的部分字段也被加密
丢包检测与拥塞控制
QUIC 改进了 TCP 的丢包检测和拥塞控制机制 (RFC 9002):
改进的 RTT 测量
QUIC 的 packet number 严格递增,不会像 TCP 的序列号那样在重传时复用
消除了 TCP 的重传歧义问题 (retransmission ambiguity)
支持更精确的 RTT 估算
丢包检测
QUIC 使用两种丢包检测机制:
基于 ACK 的检测: 如果一个数据包的 packet number 比已确认的最大 packet number 小 3 个以上,则认为丢失
基于时间的检测: 如果一个数据包发送后超过一定时间(通常为 9/8 * max(smoothed_rtt, latest_rtt))仍未被确认,则认为丢失
可插拔的拥塞控制
QUIC 的拥塞控制在用户空间实现,可以灵活替换:
New Reno: RFC 9002 中描述的默认算法
Cubic: 类似 TCP Cubic
BBR (Bottleneck Bandwidth and RTT): Google 开发的基于模型的拥塞控制
Copa: 基于延迟的拥塞控制
流量控制 (Flow Control)
QUIC 实现了两级流量控制:
流级别 (Stream-level) 流量控制
每个流有独立的接收窗口,防止单个流消耗过多缓冲区:
MAX_STREAM_DATA frame:
+------+------------+------------------+
| Type | Stream ID | Maximum Data |
+------+------------+------------------+
连接级别 (Connection-level) 流量控制
限制所有流的总数据量,防止连接整体消耗过多资源:
MAX_DATA frame:
+------+------------------+
| Type | Maximum Data |
+------+------------------+
此外,QUIC 还通过 MAX_STREAMS 帧限制并发流的数量。
WebTransport over QUIC
WebTransport 是一个新的 Web API,允许 Web 应用通过 QUIC 或 HTTP/3 与服务器进行低延迟的双向通信。它被设计为 WebSocket 和 WebRTC DataChannel 的补充或替代方案。
WebTransport API
// 建立 WebTransport 连接
const transport = new WebTransport('https://example.com:4433/wt');
await transport.ready;
// 发送不可靠的数据报 (Datagram)
const writer = transport.datagrams.writable.getWriter();
await writer.write(new Uint8Array([1, 2, 3, 4]));
// 接收数据报
const reader = transport.datagrams.readable.getReader();
const { value, done } = await reader.read();
// 创建双向流 (可靠传输)
const stream = await transport.createBidirectionalStream();
const streamWriter = stream.writable.getWriter();
await streamWriter.write(new TextEncoder().encode('Hello'));
// 创建单向流
const uniStream = await transport.createUnidirectionalStream();
const uniWriter = uniStream.getWriter();
await uniWriter.write(new Uint8Array([5, 6, 7, 8]));
// 接收服务器发起的流
const incomingStreams = transport.incomingBidirectionalStreams;
const streamReader = incomingStreams.getReader();
const { value: inStream } = await streamReader.read();
数据报与流
WebTransport 提供两种数据传输模式:
特性 |
Datagrams (数据报) |
Streams (流) |
|---|---|---|
可靠性 |
不可靠,可能丢失 |
可靠,保证有序交付 |
有序性 |
不保证顺序 |
保证顺序 |
延迟 |
最低(无重传) |
较高(需要重传) |
适用场景 |
实时音视频、游戏状态 |
文件传输、信令消息 |
流量控制 |
无 |
有 |
WebTransport 与 WebRTC DataChannel 对比
特性 |
WebRTC DataChannel |
WebTransport |
|---|---|---|
底层协议 |
SCTP over DTLS over UDP |
QUIC (HTTP/3) |
连接模型 |
P2P(需要 ICE/STUN/TURN) |
客户端-服务器 |
信令 |
需要 SDP offer/answer |
直接连接 URL |
不可靠传输 |
支持(配置 maxRetransmits=0) |
原生支持(Datagrams) |
服务器要求 |
需要信令服务器 |
标准 HTTP/3 服务器 |
NAT 穿越 |
内置(ICE) |
不需要(客户端-服务器模型) |
QUIC 用于媒体传输
Media over QUIC (MoQ)
IETF 的 Media over QUIC (MoQ) 工作组正在开发基于 QUIC 的媒体传输协议,目标是为直播、视频会议等场景提供新的传输方案。
MoQ 的核心概念:
发布-订阅模型 (Pub/Sub): 发布者发布媒体轨道,订阅者订阅感兴趣的轨道
轨道 (Track): 媒体数据的逻辑单元,如一个视频流或音频流
组 (Group): 轨道中的数据分组,通常对应一个 GOP (Group of Pictures)
对象 (Object): 组中的最小数据单元,通常对应一个媒体帧
MoQ 架构:
发布者 ──→ MoQ Relay ──→ 订阅者 A
│
└──→ 订阅者 B
│
└──→ 订阅者 C
QUIC vs RTP/UDP
将 QUIC 用于实时媒体传输面临一些挑战:
方面 |
RTP/UDP |
QUIC |
|---|---|---|
延迟 |
极低(无握手开销) |
1-RTT 握手(首次) |
可靠性 |
不可靠(适合实时媒体) |
可靠流 + 不可靠数据报 |
拥塞控制 |
应用层实现(如 GCC) |
内置(可能与媒体需求冲突) |
加密 |
SRTP(仅加密负载) |
全部加密(包括头部) |
生态系统 |
成熟,广泛部署 |
新兴,快速发展 |
中间设备 |
可被中间设备检查/优化 |
加密头部,中间设备无法干预 |
媒体传输的挑战
使用 QUIC 进行实时媒体传输需要解决以下问题:
延迟与可靠性的权衡: 实时媒体通常宁可丢帧也不愿等待重传。QUIC 的可靠流不适合这种场景,需要使用 DATAGRAM 扩展
拥塞控制适配: 传统的 QUIC 拥塞控制(如 Cubic、BBR)针对吞吐量优化,可能不适合实时媒体的低延迟需求
优先级调度: 视频的 I 帧比 P 帧更重要,音频通常比视频更重要,需要灵活的优先级机制
部分可靠性: 某些媒体帧可以丢弃(如过期的视频帧),但 QUIC 流是完全可靠的
HTTP/3 与 QUIC
HTTP/3 是 HTTP 协议的第三个主要版本,使用 QUIC 作为传输层。HTTP/3 的主要改进:
消除队头阻塞: 每个 HTTP 请求/响应使用独立的 QUIC 流
更快的连接建立: 利用 QUIC 的 1-RTT/0-RTT 握手
连接迁移: 网络切换时无需重建 HTTP 连接
改进的头部压缩: QPACK 替代 HPACK,适应 QUIC 的乱序特性
HTTP 协议栈演进:
HTTP/1.1 HTTP/2 HTTP/3
+----------+ +----------+ +----------+
| HTTP/1.1 | | HTTP/2 | | HTTP/3 |
+----------+ +----------+ +----------+
| TLS | | TLS | | QUIC |
+----------+ +----------+ | (含TLS1.3)|
| TCP | | TCP | +----------+
+----------+ +----------+ | UDP |
| IP | | IP | +----------+
+----------+ +----------+ | IP |
+----------+
QUIC 实现
主要的开源 QUIC 实现:
实现 |
组织 |
语言 |
特点 |
|---|---|---|---|
quiche |
Cloudflare |
Rust |
高性能,用于 Cloudflare CDN |
msquic |
Microsoft |
C |
Windows 原生支持,跨平台 |
ngtcp2 |
开源社区 |
C |
轻量级,与 nghttp3 配合 |
quinn |
开源社区 |
Rust |
纯 Rust 实现,async/await |
quic-go |
开源社区 |
Go |
Go 语言实现 |
aioquic |
开源社区 |
Python |
Python asyncio 实现 |
Chromium QUIC |
C++ |
Chrome 浏览器内置 |
# 使用 quiche 运行 QUIC 服务器示例
cargo run --example server -- --cert cert.pem --key key.pem --listen 0.0.0.0:4433
# 使用 curl 测试 HTTP/3
curl --http3 https://example.com/
QUIC 在 WebRTC 生态中的现状
QUIC 在 WebRTC 生态系统中的应用正在快速发展:
WebTransport: 已在主流浏览器中实现,可作为 DataChannel 的替代方案
Media over QUIC (MoQ): IETF 工作组活跃开发中,目标是标准化基于 QUIC 的媒体传输
QUIC for RTC: 一些厂商正在探索使用 QUIC 替代 RTP/SRTP 进行实时通信
信令传输: QUIC/HTTP3 可用于 WebRTC 信令通道,提供更低延迟的信令传输
未来展望:
QUIC 可能不会完全替代 RTP/SRTP,但会在特定场景中提供更好的选择
WebTransport 将成为 WebRTC DataChannel 的有力补充
MoQ 可能成为直播和大规模媒体分发的新标准
QUIC 的连接迁移特性对移动端实时通信特别有价值
协议文档结构
RFC 9000 的文档结构如下:
Streams 是 QUIC 提供的基本服务抽象:
Section 2 描述了与流相关的核心概念
Section 3 提供了流状态的参考模型
Section 4 概述了流量控制的操作
Connections 是 QUIC 端点通信的上下文:
Section 5 描述了与连接相关的核心概念
Section 6 描述了版本协商
Section 7 详细说明了建立连接的过程
Section 8 描述了地址验证和关键的拒绝服务缓解措施
Section 9 描述了端点如何将连接迁移到新的网络路径
Section 10 列出了终止打开连接的选项
Section 11 提供了流和连接错误处理的指导
Packets 和 Frames 是 QUIC 通信的基本单元:
Section 12 描述了与数据包和帧相关的概念
Section 13 定义了数据传输、重传和确认的模型
Section 14 指定了管理承载 QUIC 数据包的数据报大小的规则
编码细节:
Section 15 (版本)
Section 16 (整数编码)
Section 17 (数据包头部)
Section 18 (传输参数)
Section 19 (帧)
Section 20 (错误)