2.8 QUIC 设计原理与实践
QUIC(Quick UDP Internet Connection,快速 UDP 网络连接)是一种基于 UDP 封装的安全可靠传输协议,旨在取代 TCP,成为新一代互联网的主流传输协议。
许多人可能认为是 IETF 在推动 QUIC 替代 TCP。实际上,这项工作始于 Google。
早在 2013 年,Google 就在自家服务(如 Google.com、YouTube.com)及 Chrome 浏览器中启用了名为“QUIC”(业内称为 gQUIC)的全新传输协议。2015 年,Google 将 gQUIC 提交给 IETF,经 IETF 规范化后的 QUIC 被称为“iQUIC”。早期的 iQUIC 有多个“草稿”版本,如 h3-27、h3-29 和 h3 v1。2018 年末,IETF 发布了基于 QUIC 协议的新一代互联网标准 HTTP/3。
根据图 2-26 所示的各版本 HTTP 协议区别,可以看出 HTTP/3 最大的特点是:底层基于 UDP 、默认集成了 TLS 安全协议。
图 2-26 各个版本的 HTTP 协议对比
2.8.1 QUIC 出现的背景
QUIC 出现之前,HTTP 采用 TCP 作为底层协议来实现可靠的数据传输。
作为四十年前开发的传输层协议,TCP 的设计者显然没有预见今天移动设备盛行的场景。在移动网络环境中,TCP 暴露出来的先天设计缺陷体现在以下三个方面:
- 建立连接时延迟大:HTTPS 初次连接(TCP 握手 + TLS 握手)至少需要 3 个 RTT 才能建立。
- 队头阻塞问题:以 HTTP/2 为例,一个 TCP 连接上的所有 stream(流,HTTP/2 传输的数据单元)必须按顺序依次传输。如果一个 stream 丢失,后面的 stream 将被阻塞,直到丢失的数据重传。
- 协议僵化问题:作为一个运行了接近 40 多年的协议,许多中间设备(如防火墙和路由器)已经变得依赖某些隐式规则,打补丁或者说推动 TCP 协议更新脱离现实。
2.8.2 QUIC 的特点
在借鉴 TCP 设计经验并考虑当前网络环境的基础上,QUIC 基于 UDP 实现了一种全新的可靠传输机制,具备更低的延迟和更高的吞吐量。下面列举 QUIC 的部分重要特性,这些特性是 QUIC 被寄予厚望的关键。
1. 支持连接迁移
当用户网络环境发生变化,这在移动端相当普遍,例如 WIFI 切换到 4G 时,TCP 基于四元组的方式无法保持连接的存活。而 QUIC 由于使用 Connection ID 标识连接,当源地址发生改变时,连接不受环境变化影响,因此 QUIC 可以实现网络变化的无缝切换,从而保证连接存活和数据正常收发。
图 2-27 QUIC 支持连接迁移
2. 低时延连接
以 HTTPS 请求为例,即使是最新的 TLS 1.3 协议,初次连接也至少需要 2-RTT 才能开启数据传输。此外,像 TCP Fastopen 类补丁方案,由于协议僵化原因,实际上不会在复杂网络起到作用。
QUIC 内部集成了 TLS 安全协议,无需像 TCP 先经过三次握手,再经过 TLS 握手才开启数据传输。QUIC 初次连接只需要 1- RTT 就能开启数据传输。
图 2-28 不同协议开启数据传输时,需要的 RTT数
3. 可插拔拥塞控制
笔者曾推动升级某核心网络系统的 TCP 拥塞控制算法,过程艰难,主要因为需要升级操作系统内核版本。
大多数 QUIC 实现工作在用户空间,支持灵活“插拔”不同的拥塞控制算法,如 Cubic、BBR 和 PCC 等。这让工程师在无需深入内核开发的情况下,能灵活调整可靠传输机制和拥塞控制策略。如 Cloudflare 开发的开源 QUIC 实现 quiche,提供了 setSendAlgorithm 方法,工程师可直接选择合适的拥塞控制算法,无需经过操作系统内核。
4. 降低对丢包的影响
先来看 HTTP/2 Stream 的处理。
如图 2-29 所示,若一个属于 Stream2 的 TCP 数据包丢失(如图中标记为 5 的圆圈),将导致后续数据包的传输阻塞。该问题就是业界常常提到的“队头阻塞”(head-of-line blocking)。
相比之下,QUIC 为每个 Stream 设计了独立的控制机制,Stream 之间没有先后依赖。这意味着,如果一个属于 Stream2 的 UDP 数据包丢失,它只会影响 Stream2 的处理,不会阻塞 Stream1 和 Stream3 的传输。
这样的设计有效避免了 TCP 协议中的队头阻塞问题。
图 2-29 QUIC Stream 的设计减小了丢包的影响
此外,还需提及 QUIC 实现的另一个特性 —— QPACK。QPACK 通过更高效的头部压缩技术,减少了网络传输中的冗余数据量。这种压缩机制不仅提升了数据传输的效率,还能缓解前面提到的“队头阻塞”。
经过上述全方面的优化设计,QUIC 确保了在当今网络环境中比 TCP 更安全、更快速的连接以及更高的传输效率。
2.8.3 QUIC 实践
撰写本文时,距 HTTP/3 发布已有三年之久。那它的实际表现如何呢?2022 年,爱奇艺基础架构团队对 HTTP/1.1、HTTP/2 和 HTTP/3 在不同网络条件下的性能差异进行了测试。笔者将测试数据在此分享,供读者参考。
从请求耗时表现来看(图 2-30),相同的网络质量下,HTTP/3 的耗时比 HTTP/2 降低了近一半,证明了上述讨论不虚。
图 2-30 不同网络质量下,各协议耗时表现(耗时单位 ms)
不过,根据图 2-31 所示的网络请求成功率来看,HTTP/3 的失败率明显高于 HTTP/2。笔者“猜测”有两方面的原因:
- 某些网络环境下(如网络设备配置不当、防火墙限制),UDP 数据包更容易被丢弃。
- QUIC 作为较新的协议,在一些边缘场景(如企业内部网络、陈旧的网络设备)中,兼容性不够完善。
图 2-31 不同网络质量下,各协议失败率表现
综上所述,无论是服务端还是客户端,集成 QUIC 协议并非易事:
- 服务端层面:不仅需要适配 QUIC 协议,还要确保与 TCP 协议兼容。此外,TCP 经过多年的深度优化,QUIC 实际的效能表现是否能够与 TCP 相媲美?
- 客户端层面:需要在适配、收益之间进行成本权衡。采用 QUIC 协议的客户端必须具备降级容错能力,并准备长时间同时维护新旧两种网络库。