虽然 HTTP/3 确实有一些有前途的新概念,但遗憾的是,它们对大多数网页和用户的影响可能相对有限(但对一小部分可能至关重要)。HTTP/3 的设置和使用(正确)也非常具有挑战性,因此在配置新协议时要小心。

第 1 部分:HTTP/3 历史和核心概念

对http2的误解\不能落地的期望

HTTP/2 与 HTTP/3 协议栈比较
(HTTP/2 与 HTTP/3 协议栈比较)
协议分层是为了重用,其中TCP协议确保完整传输。提出QUIC(https://www.rfc-editor.org/rf...)协议是因为早期 TCP并没有真正考虑到最大效率。

  • TCP 需要“握手”,每个往返时间 (RTT) 可能需要 100 毫秒以上,导致明显的延迟
  • TCP 将它传输的所有数据视为单个“文件”或字节流,会有队头 (HoL) 阻塞(如果一个文件TCP包丢失,那么所有其他文件也将延迟,直到这些数据包被恢复。)

基本概念

直接在HTTP/2优化非常困难,所以我们重新构想并实现了一个更高级的 TCP 版本,并将其称为 QUIC。因为我们想让 QUIC 更容易部署,所以我们通过 UDP 运行它。

我们对 HTTP/3 的主要功能(更快的连接设置、更少的 HoL 阻塞、连接迁移等)感到兴奋,实际上都来自 QUIC。

QUIC 使用 UDP,因此设计 HTTP/3 主要是因为希望它能让它们更容易部署,因为UDP几乎被互联网上的所有设备所知并已实现.

在 UDP 之上,QUIC 基本上重新实现 TCP 的功能。QUIC 是绝对可靠的,它使用对接收到的数据包重传的确认来确保丢失的数据包仍然到达。QUIC 还建立了一个连接并有一个高度复杂的握手

QUIC 还使用所谓的流量控制拥塞控制机制来防止发送方或接收方过载,但这也会使 TCP 比原始 UDP 慢。

TLS、TCP 和 QUIC 握手持续时间
(TLS、TCP 和 QUIC 握手持续时间)

鉴于这种向永远在线的 TLS(尤其是网络流量)的明显演变,QUIC 的设计者决定将这一趋势提升到一个新的水平也就不足为奇了。他们并没有简单地为 HTTP/3 定义明文模式,而是选择将加密深深植根于 QUIC 本身,它打破了协议栈中协议之间典型的清晰分离。
与 TCP + TLS 不同,QUIC 还在数据包头和有效载荷中加密其传输层元数据
(与 TCP + TLS 不同,QUIC 还在数据包头和有效载荷中加密其传输层元数据。)

优缺点

优点

  • QUIC 对其用户更安全。

    没有办法运行明文 QUIC,因此攻击者和窃听者监听的选项也更少。(最近的研究表明HTTP/2 的明文选项是多么危险。)

  • QUIC 的连接建立速度更快。

    对于 TLS-over-TCP,两种协议都需要自己单独的握手,而 QUIC 将传输和加密握手合二为一,节省了往返(见上图)。

  • QUIC 可以更容易地进化。

    因为它是完全加密的,网络中的中间件不能再像使用 TCP 那样观察和解释其内部工作原理。因此,它们也不会因为更新失败而在较新版本的 QUIC 中(意外地)中断。如果我们想在未来为 QUIC 添加新功能,我们“只需要”更新终端设备,而不是所有的中间件。

缺点

  • 许多网络会犹豫是否允许 QUIC。

    公司可能希望在他们的防火墙上阻止它,因为检测不需要的流量变得更加困难。ISP 和中间网络可能会阻止它,因为不再容易获得诸如平均延迟和数据包丢失百分比之类的指标,从而使检测和诊断问题变得更加困难。这一切都意味着 QUIC 可能永远不会普遍可用。

  • QUIC 具有更高的加密开销。

    QUIC 使用 TLS 加密每个单独的数据包,而 TLS-over-TCP 可以同时加密多个数据包。对于高吞吐量场景,这可能会使 QUIC 变慢。

  • QUIC 使网络更加集中。
    我经常遇到的抱怨是,“谷歌正在推动 QUIC,因为它让他们可以完全访问数据,同时不与其他人共享任何数据”。我大多不同意这一点。首先,与 TLS-over-TCP 相比,QUIC 不会向外部观察者隐藏更多(或更少!)用户级信息(例如,您正在访问哪些 URL)(QUIC 保持现状)。

特性

解决HoL 阻塞

解决传输层的 HoL 阻塞是 QUIC 的主要目标之一。与 TCP 不同,QUIC 非常清楚它正在复用多个独立的字节流。

QUIC 允许 HTTP/3 绕过队头阻塞问题
(QUIC 允许 HTTP/3 绕过队头阻塞问题。)

QUIC 支持连接迁移

TCP协议下没有任何机制允许客户端让服务器知道它已经更改了 IP,所以每次网络更改都意味着无法再使用现有的 TCP 连接。重新启动 TCP 连接会产生严重影响(等待新的握手、重新启动下载、重新建立上下文)。

为了解决这个问题,QUIC 引入了一个名为连接标识符 (CID)的新概念。每个连接都在 4 元组顶部分配了另一个编号,用于在两个端点之间唯一标识它。为了防止跟踪,每次使用新网络时,QUIC 都会更改 CID。

QUIC 使用多个协商连接标识符 (CID) 来防止用户跟踪
(QUIC 使用多个协商连接标识符 (CID) 来防止用户跟踪)

在 TCP 中,连接由四个参数定义(客户端 IP 地址 + 客户端端口 + 服务器 IP 地址 + 服务器端口),当端点改变网络时,这些参数会改变。因此,有时需要重新启动这些连接,从而导致停机。QUIC 向混合中添加了另一个参数,称为连接 ID。QUIC 客户端和服务器都知道哪些连接 ID 映射到哪些连接,因此对网络变化更加健壮。

QUIC 灵活且可扩展

  1. QUIC 几乎完全加密的事实意味着,如果我们想部署更新版本的 QUIC,我们只需要更新端点(客户端和服务器),而不是所有中间件。
  2. QUIC 不使用单个固定的数据包头来发送所有协议元数据。相反,QUIC 具有较短的数据包标头,并在数据包有效载荷内使用各种“帧”(类似于微型专用数据包)来传达额外信息。例如,有一个ACK框架(用于确认)、一个NEW_CONNECTION_ID框架(用于帮助建立连接迁移)和一个STREAM框架(用于携带数据),如下图所示。QUIC 使用单独的帧来发送元数据,而不是一个大的固定数据包头。
  3. QUIC 使用自定义 TLS 扩展来携带所谓的传输参数。这些允许客户端和服务器为 QUIC 连接选择配置。这意味着他们可以协商启用哪些功能(例如,是否允许连接迁移、支持哪些扩展等)并为某些机制(例如,支持的最大数据包大小、流量控制限制)传达合理的默认值。
  4. 大多数实现目前是在“用户态”中完成的(与 TCP 不同,后者通常在“内核态”中完成)。

虽然 QUIC 现在已经标准化,但它确实应该被视为QUIC 1 ,并且有明确的意图来创建版本 2 和更快的版本。

第 2 部分:HTTP/3 性能特性

QUIC 和 HTTP/3 确实具有巨大的 Web 性能潜力,但主要用于慢速网络上的用户。如果您的普通访问者使用的是快速有线或蜂窝网络,他们可能不会从新协议中受益太多。

拥塞控制

性能的一个方面是关于传输协议如何有效地使用网络的全部(物理)带宽(即大致每秒可以发送或接收多少数据包)。这反过来会影响页面资源的下载速度。有些人声称 QUIC 在某种程度上比 TCP 好得多,但事实并非如此。

连接不知道它可以安全或公平地预先使用多少带宽,并且该带宽会随着用户加入、离开和使用网络而变化。为了解决这个问题,TCP 将通过使用称为拥塞控制的机制不断尝试发现可用带宽。
TCP 拥塞控制的简化示例,从 10 个数据包的发送速率开始
(TCP 拥塞控制的简化示例,从 10 个数据包的发送速率开始)

尽管 TCP 的拥塞控制使其稳健,但这也意味着需要一段时间才能达到最佳发送速率,具体取决于 RTT 和实际可用带宽。对于网页加载,这种慢启动方法还会影响诸如FCP(首次内容绘制)等指标,因为在前几次往返中只能传输少量数据(几十到几百 KB)。

并非QUIC不使用拥塞控制,实际上使用与 TCP 非常相似的带宽管理技术。它也从较低的发送速率开始,并随着时间的推移而增长,使用确认作为衡量网络容量的关键机制。拥塞控制算法今天仍在大力发展,例如,我们可能需要调整一些东西以充分利用 5G

QUIC的延迟确认频率扩展提议

虽然默认情况下,QUIC 每收到 2 个数据包都会发送一个确认,但此扩展允许端点确认,例如,每 10 个数据包。这已被证明可以为卫星和非常高带宽的网络带来很大的速度优势,因为传输确认数据包的开销降低了。为 TCP 添加这样的扩展需要很长时间才能被采用,而对于 QUIC 来说,部署起来要容易得多。

拥塞控制算法不是特定于 TCP 或 QUIC 的;它们可以被任何一种协议使用,事实上,大多数生产级 QUIC 实现都对CubicBBR进行了自定义实现。

0-RTT 连接设置

由于TCP设计成不依赖TLS下使用,导致不支持在握手期间发送非TCP内容。导致在我们可以发送第一个 HTTP 请求之前至少需要两次往返的握手等待时间开销,这是低效的。

QUIC 从一开始就考虑到了 TLS,因此在单一机制中结合了传输和加密握手。这意味着 QUIC 握手总共只需要一次往返即可完成,这比 TCP + TLS 1.3 少一次往返。

TLS、TCP 和 QUIC 握手持续时间
(TCP + TLS 与 QUIC 连接设置)

虽然最坏的情况(TCP + TLS 1.2,(a))QUIC 比 TCP 快两个甚至三个往返,但是现代 TCP + TLS 1.3 也“只”进行两次往返(很少显示(b))

会话恢复和 0-RTT 经常被错误解释为 QUIC 特定功能的事情。实际上,这些实际上是TLS 功能,它们已经以某种形式出现在 TLS 1.2 中,现在在TLS 1.3中完全成熟。

QUIC 使用0-RTT的更快连接设置实际上更多的是微优化,而不是革命性的新功能。与最先进的 TCP + TLS 1.3 设置相比,它最多可以节省一次往返。在第一次往返中实际可以发送的数据量还受到许多安全考虑因素的限制。因此,如果您的用户使用延迟非常高的网络(例如,RTT 超过 200 毫秒的卫星网络),或者您通常不发送大量数据,则此功能将大放异彩。在其他情况下,您最多只能获得几十毫秒,如果您已经在使用 CDN,则甚至更少。

UDP 和 TLS 性能
QUIC 使用 UDP 和重加密使它比 TCP 慢一点(但情况正在改善),是因为TCP和UDP通常直接在OS”快速内核中实现。相比之下,TLS 和 QUIC 的实现大多在较慢的用户空间中。
TCP 和 QUIC 之间的实现差异
(TCP 和 QUIC 之间的实现差异)
对于 TCP,这些开销远低于 UDP,这主要是因为从历史上看,TCP 的使用比 UDP 多得多。但在过去的五年中,大多数操作系统也为UDP添加了优化选项

其次,QUIC 有很多开销,因为它单独加密每个数据包。实践中,优化的加密库和允许批量加密 QUIC 数据包标头的巧妙方法。最近,Google QUIC 堆栈最优化的版本目前比 TCP + TLS 慢约 20%

第 3 部分:实用的 HTTP/3 部署选项

对页面和资源的更改

如果您已经在使用 HTTP/2,那么在迁移到 HTTP/3 时您可能不需要对页面或资源进行任何更改!

服务器和网络

这些实现主要处理 HTTP/3 和 QUIC 的东西;它们本身并不是真正成熟的网络服务器。

Pythonaioquic
Goquic-go
Rust(quiche)[https://github.com/cloudflare...] (Cloudflare), Quinn, Neqo (Mozilla)
C and C++mvfst (Facebook), MsQuic, (Microsoft), (Google), ngtcp2, LSQUIC (Litespeed), picoquic, quicly (Fastly)

开箱即用的完整 Web 服务器的部分列表以及它们当前的 HTTP/3 支持如下:

  • Apache

    支持目前尚不清楚。什么都没有宣布。它可能还需要 OpenSSL。(但请注意,有一个Apache Traffic Server实现。)

  • NGINX

    这是一个自定义实现。这是相对较新的,并且仍然是高度实验性的。预计将在 2021 年底合并到主线 NGINX。这是相对较新的,并且仍然是高度实验性的。请注意,还有一个补丁可以在 NGINX 上运行 Cloudflare的quic库,目前可能更稳定。

  • Node.js

    这在内部使用 ngtcp2 库。它被 OpenSSL 进度阻止,尽管他们计划切换到 QUIC-TLS fork 以更快地获得一些工作

  • IIS

    目前尚不清楚IIS支持,也没有公布任何内容。不过,它可能会在内部使用 MsQuic 库。

  • Hypercorn

    这种集成aioquic,与实验的支持。

  • Caddy

    这使用 quic-go,完全支持。

  • H2O

    这个用得很快,完全支持。

  • Litespeed

    这使用 LSQUIC,完全支持。

客户端

大多数流行的浏览器已经(实验性的)HTTP/3 支持!

浏览器对 HTTP/3 的支持相当成熟

参考资料

[HTTP/3 From A To Z: Core Concepts (Part 1)
](https://www.smashingmagazine....)

HTTP/3: Performance Improvements (Part 2)

[HTTP/3: Practical Deployment Options (Part 3)
](https://www.smashingmagazine....)


seasonley
607 声望693 粉丝

一切皆数据