Professional Documents
Culture Documents
HTTP/3:实际部署选项(第 3 部分)
快 速 摘 要 ↬ 经过近五年的开发,新的HTTP / 3协议已接近其最终形
式。让我们仔细看看部署和测试HTTP / 3所涉及的挑战,以及如何以
及是否应该更改您的网站和资源。
您好,欢迎来到这个由三部分组成的系列的最后一部分,介绍新的HTTP
/ 3和QUIC协议!如果在前两部分之后 - HTTP / 3历史和核心概念 (↦
https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)以及HTTP / 3性
能功能 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/) - 您确信开始使用新协议是一个好主意(您应该这样做!),那么
最后一部分包括您入门所需的所有知识!
首先,我们将讨论您需要对页面和资源进行哪些更改才能以最佳方式使用新协
议(这是简单的部分)。接下来,我们将介绍如何设置服务器和客户端(除非
您使用内容交付网络(CDN),否则这是困难的部分)。最后,我们将看到您
可以使用哪些工具来评估新协议的性能影响(这是几乎不可能的部分,至少现
在是这样)。
第 1 部分:HTTP/3 历史和核心概念 (↦
https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)
第2部分:HTTP / 3性能特性 (↦
https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/)
这一部分更深入,技术性更强。已经了解基础知识的人可以从这里
开始。
对页面和资源的更改# (↦ #Changes-To-Pages-And-
Resources)
让我们从一些好消息开始:如果您已经在使用HTTP / 2,那么在迁移到HTTP /
3时,您可能不必对页面或资源进行任何更改!这是因为,正如我们在第 1 部分
(↦ https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/#why-do-we-need-http-3)和
第 2 部分中 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/#http-3-features)所解释的那样,HTTP/3 实际上更像是 HTTP/2-over-QUIC,而
这两个版本的高级功能保持不变。因此,对HTTP / 2所做的任何更改或优化仍然
适用于HTTP / 3,反之亦然。
1. 单连接# (↦ #1-SINGLE-CONNECTION)
2. 服务器分片和连接合并# (↦ #2-SERVER-SHARDING-AND-
CONNECTION-COALESCING)
在实践中,切换到单一连接设置非常困难,因为许多页面被分片到不同的主机
名甚至服务器(如和)。这是因为浏览器只为每个单独的主机名打开最多六个
连接,因此拥有多个主机名可以允许更多连接!如果不更改此HTTP / 1.1设置,
HTTP / 2仍将打开多个连接,从而降低其他功能(例如优先级(见下文))的实
际工作能力。 img1.example.com img2.example.com
因此,最初的建议是撤消服务器分片,并尽可能多地在单个服务器上整合资
源。HTTP/2甚至提供了一个功能,使从HTTP/1.1设置的转换更容易,称为连接合
并 (↦ https://daniel.haxx.se/blog/2016/08/18/http2-connection-coalescing/)。粗略地说,如果两
个主机名解析为相同的服务器IP(使用DNS)并使用类似的TLS证书,则浏览器
甚至可以跨两个主机名重用单个连接。
在实践中,连接合并可能很难正确 (↦ https://nooshu.github.io/blog/2019/12/17/http2-and-sri-
dont-always-get-on/),例如,由于涉及CORS的几个微妙的安全问题 (↦
https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/#requests-without-credentials-use-a-
separate-connection)。即使您设置正确,您仍然很容易地以两个单独的连接结束。
问题是,这并不总是坏事。首先,由于优先级和多路复用(见下文)的实现不
佳,单个连接可能比使用两个或更多连接慢 (↦
https://twitter.com/zachleat/status/1055219667894259712)。其次,由于竞争拥塞控制器,使
用过多的连接可能会导致早期数据包丢失。然而,仅使用几个(但仍然不止一
个)可以很好地平衡拥塞增长和更好的性能,特别是在高速网络上。由于这些
原因,我相信即使使用HTTP / 2,一点点分片仍然是一个好主意(例如,两到
四个连接)。事实上,我认为大多数现代HTTP / 2设置的表现都很好,因为它们
在关键路径中仍然有一些额外的连接或第三方负载。
3. 资源捆绑和内联# (↦ #3-RESOURCE-BUNDLING-AND-INLINING)
例如,您可以降低 (↦ https://blog.khanacademy.org/forgo-js-packaging-not-so-fast/)压缩效率
(↦ https://jakearchibald.com/2021/f1-perf-part-7/#lots-of-little-resources-vs-one-big-resource),因为这
可以更好地处理更多数据。此外,每个额外的请求或文件都有固有的开销,因
为它需要由浏览器和服务器处理 (↦
https://twitter.com/yoavweiss/status/1254650804524507136)。这些成本可以加起来,例如,
与几个大文件相比,数百个小文件。在我们自己的早期测试 (↦
https://speeder.edm.uhasselt.be/webist/files/h2bestpractices_RobinMarx_WEBIST2017.pdf)中,我发
现大约40个文件的回报严重递减。虽然这些数字现在可能更高一些 (↦
https://twitter.com/youyuxi/status/1425933472871456777),但文件请求在HTTP / 2中仍然不
像最初预测的那样便宜。最后,不内联资源会增加延迟成本,因为需要请求文
件。这与优先级和服务器推送问题(见下文)相结合,意味着即使在今天,您
仍然最好内联一些关键的CSS (↦ https://calendar.perfplanet.com/2020/implementing-critical-
css-from-cms-to-cls/)。也许有一天,Resource Bundles提案 (↦
https://github.com/WICG/resource-bundles)会有所帮助,但现在还不行。
当然,对于HTTP / 3来说,所有这些都仍然是正确的。尽管如此,我还是读到
有人声称许多小文件会比QUIC更好,因为更多并发活跃的独立流意味着从HoL
阻止删除中获得更多利润(正如我们在第2部分中 (↦
https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#head-of-line-
blocking-removal)讨论的那样)。我认为这可能有一定的道理,但是,正如我们在
第2部分中也看到的那样,这是一个非常复杂的问题,有很多移动参数。我不认
为这些好处会超过所讨论的其他成本,但需要更多的研究。(一个令人愤慨的
想法是让每个文件的大小精确到适合单个QUIC数据包,完全绕过HoL阻止。我
将接受任何实现资源捆绑器的初创公司的版税。;))
4. 优先级# (↦ #4-PRIORITIZATION)
为了能够在单个连接上下载多个文件,您需要以某种方式多路复用它们。如第 2
部分 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#head-
of-line-blocking-removal)所述,在 HTTP/2 中,此多路复用是使用其优先级系统进行
引导的。这就是为什么在同一连接上请求尽可能多的资源很重要的原因 - 以便能
够正确地将它们彼此确定优先级!然而,正如我们也看到的那样,这个系统非
常复杂,导致它在实践中经常被糟糕地使用和实现 (↦
https://github.com/andydavies/http2-prioritization-issues)(见下图)。反过来,这意味着对
HTTP / 2的其他一些建议 - 例如减少捆绑,因为请求很便宜,以及减少服务器分
片,以充分利用单个连接(见上文) - 在实践中表现不佳。
(↦ https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/e8aef424-b7d6-
44ce-ba69-d349439fcaa5/http2-prioritization.png)
可悲的是,作为一个普通的Web开发人员,这是你无法做很多事情的事情,因
为它主要是浏览器和服务器本身的问题。但是,您可以通过不使用太多的单个
文件(这将降低竞争优先级的机会)和仍然使用(有限的)分片来尝试缓解此
问题。另一种选择是使用各种影响优先级的技术,例如延迟加载 (↦
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading),JavaScript 异步
和 延迟 (↦ https://addyosmani.com/blog/script-priorities/),以及资源提示(例如 预加载 (↦
https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload))。在内部,这些主要
更改资源的优先级,以便更早或更晚地发送它们。但是,这些机制可能(并且
确实)遭受错误的影响 (↦ https://bugs.chromium.org/p/chromium/issues/detail?id=788757)。
此外,不要指望在一堆资源上打耳光,让事情变得更快:如果一切都突然成为
高优先级,那么什么都不是!通过使用 预加载 之类的东西 (↦
https://www.debugbear.com/blog/rel-preload-problems),甚至很容易 (↦
https://twitter.com/programmingart/status/1351557858354225159)延迟 (↦
https://twitter.com/csswizardry/status/1349681832393109510)实际的关键资源。 preload
正如第 2 部分 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/#head-of-line-blocking-removal)所述,HTTP/3 从根本上改变了此优先级系统的内
部结构。我们希望这意味着其实际部署中的错误和问题将大大减少,因此至少
应该解决其中的一些问题。然而,我们还不能确定,因为今天很少有HTTP / 3服
务器和客户端 (↦
https://qlog.edm.uhasselt.be/epiq/files/QUICImplementationDiversity_Marx_final_11jun2020.pdf)完全
实现这个系统。尽管如此,优先级的基本概念不会改变。如果不真正了解内部
发生的情况,您仍然无法使用诸如此类技术,因为它可能仍然会错误地确定资
源的优先级。 preload
5. 服务器推送和首次飞行# (↦ #5-SERVER-PUSH-AND-FIRST-FLIGHT)
服务器推送允许服务器发送响应数据,而无需先等待来自客户端的请求。同
样,这在理论上听起来很棒,它可以代替内联资源(见上文)。但是,如第 2
部分 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#http-
3-features)所述,由于拥塞控制、缓存、优先级和缓冲方面的问题, (↦
https://calendar.perfplanet.com/2016/http2-push-the-details/)推送很难正确使用。总体而言,
除非您真的知道自己在做什么,否则最好不要将其用于一般网页加载,即使这
样,它也可能是一个微优化 (↦ https://twitter.com/patmeenan/status/1359337536125075460)。
不过,我仍然相信它可以在(REST)API中占有一席之地,您可以在其中在预热
连接上推送(JSON)响应中链接到的子资源 (↦ https://github.com/dunglas/vulcain)。对
于 HTTP/2 和 HTTP/3 都是如此。
为了概括一下,我觉得可以为TLS会话恢复和0-RTT做出类似的评论,无论是通
过TCP + TLS还是通过QUIC。如第 2 部分 (↦
https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#0-rtt-
connection-set-up)所述,0-RTT 类似于服务器推送(通常使用),因为它尝试加速
页面加载的第一阶段。但是,这意味着它当时可以实现的目标同样有限(由于
安全问题,在QUIC中更是如此)。因此,微优化再次成为您可能需要在低水平
上微调事物才能真正从中受益的方式。想想我曾经非常兴奋地尝试将服务器推
送与0-RTT相结合。
这一切意味着什么?# (↦ #WHAT-DOES-IT-ALL-MEAN)
以上所有内容都归结为一个简单的经验法则:应用您在网上找到的大多数典型
HTTP / 2建议,但不要将它们推向极端。
以下是一些具体的观点,这些观点主要适用于HTTP / 2和HTTP / 3:
01 在关键路径上大约一到三个连接上分片资源(除非您的用户大多位于低带
宽网络上),在需要时使用 预连接 和 dns 预取 (↦
https://www.smashingmagazine.com/2019/04/optimization-performance-resource-hints/)。
02 按路径或功能或每个更改频率在逻辑上捆绑子资源。每页五到十个
JavaScript和五到十个CSS资源应该没问题。内联关键CSS仍然是一个很好的
优化。
03 请谨慎使用复杂的功能,例如 。 preload
是火箭科学。但是,更困难的是正确设置HTTP / 3服务器,客户端和工具。
服务器和网络# (↦ #Servers-And-Networks)
正如您现在可能已经了解的那样,QUIC和HTTP / 3是相当复杂的协议。从头开
始实现它们将涉及阅读(和理解!数百页,分布在七个以上的文档中 (↦
https://quicwg.org/)。幸运的是,多家公司已经在开源QUIC和HTTP / 3实现 (↦
https://github.com/quicwg/base-drafts/wiki/Implementations)上工作了五年多,因此我们有几
个成熟而稳定的选项可供选择。
一些最重要和最稳定的包括以下内容:
语
实现
言
蟒 aioquic (↦ https://github.com/aiortc/aioquic)
去 quic-go (↦ https://github.com/lucas-clemente/quic-go)
乳蛋饼 (↦ https://github.com/cloudflare/quiche)(Cloudflare),Quinn (↦
锈 https://github.com/quinn-rs/quinn),Neqo (↦ https://github.com/mozilla/neqo)
(Mozilla)
但是,这些实现中的许多(也许是大多数)主要负责HTTP / 3和QUIC的东西;它
们本身并不是真正成熟的Web服务器。当涉及到典型的服务器(想想NGINX,
Apache,Node.js)时,由于几个原因,事情有点慢。首先,他们的开发人员中
很少有人从一开始就参与HTTP / 3,现在他们必须迎头赶上。许多人通过在内部
使用上面列出的实现之一作为库来绕过这一点,但即使是这种集成也很困难。
其次,许多服务器依赖于第三方TLS库,如OpenSSL。同样,这是因为TLS非常
复杂并且必须安全,因此最好重用现有的,经过验证的工作。但是,虽然QUIC
与TLS 1.3集成,但它的使用方式与TLS和TCP的交互方式大不相同。这意味着
TLS库必须提供特定于QUIC的API (↦ https://daniel.haxx.se/blog/2019/01/21/quic-and-missing-
apis/),而他们的开发人员长期以来一直不愿意或缓慢地做到这一点。特别是这
里的问题,是OpenSSL,它推迟了对QUIC的支持 (↦
https://www.openssl.org/blog/blog/2020/02/17/QUIC-and-OpenSSL/),但它也被许多服务器使
用。这个问题变得如此严重,以至于 Akamai 决定启动一个特定于 QUIC 的
OpenSSL 分支,称为 quictls (↦ https://github.com/quictls/openssl)。虽然存在其他选项和
解决方法 (↦ https://daniel.haxx.se/blog/2021/04/02/where-is-http-3-right-now/),但对 QUIC 的
TLS 1.3 支持仍然是许多服务器的阻碍因素,并且预计会在一段时间内保持这种
状态。
您应该能够开箱即用的完整Web服务器的部分列表,以及它们当前的HTTP / 3支
持,如下所示:
Apache
支持目前尚不清楚。什么都没有宣布。它可能还需要OpenSSL。(请注
意,有一个Apache流量服务器 (↦ https://cwiki.apache.org/confluence/display/TS/QUIC)
实现。
NGINX (↦ https://quic.nginx.org/)
这是一个自定义实现。这是相对较新的,仍然是高度实验性的。预计将于
2021年底并入主线NGINX (↦ https://www.nginx.com/blog/our-roadmap-quic-http-3-
support-nginx/)。这是相对较新的,仍然是高度实验性的。请注意,在
NGINX上也有一个补丁可以运行Cloudflare的乳蛋饼库 (↦
https://blog.cloudflare.com/experiment-with-http-3-using-nginx-and-quiche/),目前可能更
稳定。
Node.js
这在内部使用 ngtcp2 库。它被OpenSSL进度阻止了 (↦
https://github.com/nodejs/node/pull/37067),尽管他们计划切换到QUIC-TLS分叉,
以便更快地工作 (↦ https://github.com/nodejs/node/issues/38478)。
IIS
支持目前尚不明确,并且尚未宣布任何内容。不过,它可能会在内部使用
MsQuic库。
Hypercorn (↦ https://pgjones.dev/blog/http-1-2-3-2019/)
这集成了aioquic,具有实验支持。
Caddy (↦ https://ma.ttias.be/how-run-http-3-with-caddy-2/)
This 使用 quic-go,并得到全面支持。
H2O (↦ https://github.com/h2o/h2o)
这使用quicly,具有完全支持。
Litespeed (↦ https://github.com/litespeedtech/lsquic)
这使用LSQUIC,具有完全支持。
请注意一些重要的细微差别:
即使“完全支持”也意味着“目前为止”,而不一定是“生产就绪”。例如,许多
实现尚未完全支持连接迁移、0-RTT、服务器推送或 HTTP/3 优先级。
其他未列出的服务器,如Tomcat,(据我所知)尚未发布任何公告。
在列出的Web服务器中,只有Litespeed,Cloudflare的NGINX补丁和H2O是
由密切参与QUIC和HTTP / 3标准化的人制作的,因此这些最有可能在早期
工作得最好。
如您所见,服务器环境尚未完全实现,但肯定已经有设置HTTP / 3服务器的选
项。但是,简单地运行服务器只是第一步。配置它和网络的其余部分更加困
难。
网络配置# (↦ #NETWORK-CONFIGURATION)
如第 1 部分 (↦ https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/#what-is-
quic)所述,QUIC 在 UDP 协议之上运行,使其更易于部署。但是,这主要意味着
大多数网络设备可以解析和理解UDP。可悲的是,这并不意味着UDP是普遍允
许的。由于UDP通常用于攻击,并且除了DNS之外,对正常的日常工作并不重
要,因此许多(企业)网络和防火墙几乎完全阻止了该协议。因此,可能需要
明确允许 UDP 进入/从 HTTP/3 服务器。QUIC 可以在任何 UDP 端口上运行,
但预计端口 443(通常也用于 TCP 上的 HTTPS)是最常见的。
QUIC 级别的元数据(如数据包编号),但也包括指示连接关闭的信号。对于
TCP,防火墙会主动跟踪所有这些元数据,以检查预期行为。(在携带数据的数
据包之前,我们是否看到完全握手?数据包是否遵循预期的模式?有多少个打
开的连接?正如我们在第1部分中 (↦ https://www.smashingmagazine.com/2021/08/http3-core-
concepts-part1/#why-do-we-need-http-3)所看到的,这正是TCP不再具有实际可进化性的
原因之一。但是,由于QUIC的加密,防火墙可以少做这种连接级跟踪逻辑,
并且它们可以检查的少数位相对复杂。
因此,许多防火墙供应商目前建议阻止 QUIC,直到他们可以更新其软件。但
是,即使在那之后,许多公司可能也不想允许它,因为防火墙QUIC支持将始终
远低于他们习惯的TCP功能。
由于连接迁移功能,这一切都变得更加复杂。正如我们所看到的 (↦
https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/#quic-supports-connection-
migration),此功能允许使用连接 ID (CID) 从新的 IP 地址继续连接,而无需执
行新的握手。但是,对于防火墙来说,这看起来好像在没有首先使用握手的情
况下使用新连接,这可能也是攻击者发送恶意流量。防火墙不能只使用QUIC
CID,因为它们也会随着时间的推移而变化以保护用户的隐私!因此,服务器需
要与防火墙通信,以了解预期的CID,但这些东西都不存在。
对于更大规模的设置,负载均衡器也存在类似的问题。这些计算机将传入连接
分布在大量后端服务器上。当然,一个连接的流量必须始终路由到同一后端服
务器(其他人不知道该如何处理它!对于TCP,这可以简单地基于4元组 (↦
https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/#quic-supports-connection-
migration)完成,因为这永远不会改变。但是,通过 QUIC 连接迁移,这不再是一
种选择 (↦ https://youtu.be/pq_xk_Pecu4?t=1226)。同样,服务器和负载平衡器需要以某
种方式就选择哪些 CID 达成一致,以便允许确定性路由。然而,与防火墙配置
不同的是,已经有一个建议 (↦ https://tools.ietf.org/html/draft-ietf-quic-load-balancers)来设置
它(尽管这远未得到广泛实施)。
SYN洪水 (↦ https://en.wikipedia.org/wiki/SYN_flood)),QUIC包含重试功能 (↦
https://www.rfc-editor.org/rfc/rfc9000.html#name-address-validation-using-re)。这允许服务器验
证它是否是一个行为良好的客户端,而不必同时保持任何状态(相当于TCP SYN
Cookie (↦ https://en.wikipedia.org/wiki/SYN_cookies))。当然,此重试过程最好发生在后
端服务器之前的某个位置,例如,在负载平衡器上。同样,这需要额外的配置
和通信 (↦ https://tools.ietf.org/html/draft-ietf-quic-load-balancers-06#section-7)来设置。
这些只是网络和系统管理员在使用QUIC和HTTP / 3时遇到的最突出的问题。还
有几个,其中一些我已经谈到过 (↦ https://youtu.be/pq_xk_Pecu4?t=981)。QUIC RFC 还
有两个单独的 (↦ https://datatracker.ietf.org/doc/html/draft-ietf-quic-applicability)随附文档 (↦
https://datatracker.ietf.org/doc/html/draft-ietf-quic-manageability),用于讨论这些问题及其可
能的(部分)缓解措施。
这一切意味着什么?# (↦ #WHAT-DOES-IT-ALL-MEAN-1)
HTTP/3和QUIC是复杂的协议,依赖于大量的内部机制。并非所有这一切都已经
准备好进入黄金时段,尽管您已经有一些选择可以在后端部署新协议。但是,
最突出的服务器和底层库(如OpenSSL)可能需要几个月甚至几年的时间才能更
新。
即使这样,正确配置服务器和其他网络中介,以便协议可以以安全和最佳的方
式使用,在更大规模的设置中也将是非同小可的。您需要一个好的开发和运营
团队来正确实现此过渡。
因此,特别是在早期,最好依靠大型托管公司或CDN为您设置和配置协议。如
第 2 部分 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/#packet-loss-resilience)所述,这是 QUIC 最有可能获得回报的地方,使用 CDN
是您可以执行的关键性能优化之一。我个人建议使用Cloudflare或Fastly,因为
他们已经密切参与了标准化过程,并将拥有最先进和经过良好调整的实现。
在开始之前,让我们从一些好消息开始:大多数流行的浏览器已经具有(实验
性的)HTTP / 3支持!具体而言,在撰写本文时,以下是支持状态(另请参阅
caniuse.com (↦ https://caniuse.com/http3)):
(↦ https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/9d4aedbb-8464-
4062-93d4-986989202121/caniuse-h3.png)
浏览器对HTTP / 3的支持已经相当成熟。(资料来源:caniuse.com (↦
https://caniuse.com/http3))(大预览 (↦ https://cloud.netlifyusercontent.com/assets/344dbf88-
fdf9-42bb-adb4-46f01eedd629/9d4aedbb-8464-4062-93d4-986989202121/caniuse-h3.png))
谷歌浏览器(版本91+):默认启用。
其他浏览器:我还没有知道的信号(尽管其他内部使用Chromium的浏览
器,如Brave,理论上也可以开始启用它)。
请注意一些细微差别:
大多数浏览器正在逐步推出,因此并非所有用户从一开始就默认启用
HTTP / 3支持。这样做是为了限制单个被忽略的 Bug 可能影响许多用户或
服务器部署过载的风险。因此,即使在最近的浏览器版本中,您也有很小
的几率默认不会获得HTTP / 3,并且必须手动启用它 (↦
https://caniuse.com/http3)。
与服务器一样,HTTP/3 支持并不意味着此时已实现或正在使用所有功能。
特别是,0-RTT、连接迁移、服务器推送、动态 QPACK 标头压缩和 HTTP/3
优先级可能仍然丢失、禁用、谨慎使用或配置不当。
如果要在浏览器外部(例如,在本机应用中)使用客户端 HTTP/3,则必须
集成上面列出的 (↦ https://www.smashingmagazine.com/2021/09/http3-practical-
集成上面列出的 ( https://www.smashingmagazine.com/2021/09/http3 practical
deployment-options-part3/#servers-and-networks)库之一或使用 cURL (↦
https://github.com/curl/curl/blob/master/docs/HTTP3.md)。苹果将很快将原生HTTP / 3
和QUIC支持引入其在macOS和iOS上的内置网络库 (↦
https://developer.apple.com/videos/play/wwdc2021/10094/),微软正在将QUIC添加到
Windows内核及其.NET环境中 (↦ https://docs.microsoft.com/en-
us/aspnet/core/fundamentals/servers/kestrel/http3?view=aspnetcore-6.0),但据我所知,类
似的原生支持尚未宣布用于Android等其他系统。
ALT-SVC# (↦ #ALT-SVC)
即使您已经设置了一个与HTTP / 3兼容的服务器并且正在使用更新的浏览器,您
也可能会惊讶地发现HTTP / 3实际上并没有被一致地使用。为了理解原因,让
我们假设你是浏览器一会儿。您的用户已请求您导航到(您以前从未访问过的
网站),并且您已使用 DNS 将其解析为 IP。将一个或多个 QUIC 握手数据包发
送到该 IP。现在有几件事可能会出错: example.com
01 服务器可能不支持 QUIC。
03 握手数据包可能会在传输过程中丢失。
但是,您如何知道(哪个)发生了这些问题之一?在所有这三种情况下,您永
远不会收到对握手数据包的回复。您唯一能做的就是等待,希望回复可能仍然
会进来。然后,经过一段时间的等待(超时),您可能会认为HTTP / 3确实存在
问题。此时,您将尝试打开与服务器的 TCP 连接,希望 HTTP/2 或 HTTP/1.1 能够
正常工作。
如您所见,这种类型的方法可能会引入重大延迟,尤其是在许多服务器和网络
尚不支持QUIC的最初年份。一个简单但幼稚的解决方案是同时打开QUIC和
TCP连接,然后使用首先完成的握手。这种方法被称为“连接赛车”或“快乐的眼
球 (↦ https://en.wikipedia.org/wiki/Happy_Eyeballs)”。虽然这当然是可能的,但它确实有
相当大的开销。即使失去的连接几乎立即关闭,它仍然占用客户端和服务器上
的一些内存和CPU时间(特别是在使用TLS时)。最重要的是,这种方法还存在
其他问题,涉及IPv4与IPv6网络以及前面讨论的重放攻击 (↦
https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#0-rtt-
connection-set-up)(我的演讲 (↦ https://youtu.be/pq_xk_Pecu4?t=1545)将更详细地介绍)。
因此,对于QUIC和HTTP / 3,浏览器宁愿安全地使用它,并且只有在知道服务
器支持它时才尝试QUIC。因此,第一次联系新服务器时,浏览器将仅通过 TCP
连接使用 HTTP/2 或 HTTP/1.1。然后,服务器可以让浏览器知道它还支持
HTTP/3 进行后续连接。这是通过在通过 HTTP/2 或 HTTP/1.1 发回的响应上设置
一个特殊的 HTTP 标头来完成的。此标头称为 ,代表“替代服务 (↦
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc)”。 可用于让浏览器知道某
个服务也可以通过另一个服务器(IP和/或端口)访问,但它也允许指示替代协
议。这可以在下面的图1中看到。 Alt-Svc Alt-Svc
(↦ https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/90f995f5-6b02-
4884-a602-f5a526fb40e2/facebook-alt-svc.png)
目前正在进行一些工作,以在某种程度上改进这一两步过程。这个
想法是使用称为SVCB和HTTPS (↦ https://datatracker.ietf.org/doc/html/draft-
ietf-dnsop-svcb-https)的新DNS记录,它们将包含类似于 中的信息。因
此,客户端可以在 DNS 解析步骤中 (↦
https://docs.google.com/document/d/1k461sRbddjDGj7Q8f-ZKHZvmB-
ENUWSdX_3Fpp2dmXQ)发现服务器支持 HTTP/3,这意味着它可以从第
一个页面加载开始尝试 QUIC,而不必首先通过 HTTP/2 或 HTTP/1.1。
有关此内容和 的更多信息,请参阅去年关于 HTTP/2 的 Web Almanac
章节 (↦ https://almanac.httparchive.org/en/2020/http2#deploying-and-discovering-
http3)。 Alt-Svc Alt-Svc Alt-Svc
虽然这在生产级设置中应该是可管理的(因为,例如,单个Apache或NGINX实
例可能会同时支持所有三个HTTP版本),但在(本地)测试设置中可能会更烦
人(我已经可以看到自己忘记添加标头或搞砸它们)。由于(当前)缺乏浏览
器错误日志和DevTools指标,这意味着弄清楚为什么设置不起作用可能很困
难。 Alt-Svc
其他问题# (↦ #ADDITIONAL-ISSUES)
仍然可以通过一些奇怪的 (↦ https://github.com/GoogleChrome/samples/issues/697)命令行标
志(因为通用代码 (↦ https://github.com/marten-seemann/chrome-quic-interop-
runner/blob/master/run.py#L45)还不适用于QUIC),通过使用每个开发人员的证书
(尽管设置这可能很繁琐),或者在开发PC上设置真正的证书(但这很少是大
型团队的选择,因为你必须与每个开发人员共享证书的私钥)来绕过它 (↦
https://centrifugal.github.io/centrifugo/blog/quic_web_transport/#generate-self-signed-tls-
certificates)。最后,虽然您可以安装自定义根证书 (↦
https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-
environment-in-5-minutes-7af615770eec/),但还需要在启动 Chrome 时 (↦
https://www.chromium.org/quic/playing-with-quic)同时传递 和 标志(见下文 (↦
https://www.smashingmagazine.com/2021/09/http3-practical-deployment-options-part3/#tools-and-
testing))。幸运的是,就目前而言,只有Chrome如此严格,希望其开发人员会
随着时间的推移放松他们的方法。 --ignore-certificate-errors
--origin-to-force-quic-on --ignore-certificate-errors-spki-list
这一切意味着什么?# (↦ #WHAT-DOES-IT-ALL-MEAN-2)
除了在服务器端设置HTTP / 3和QUIC所涉及的挑战之外,在让浏览器一致地使
用新协议方面也存在困难。这是由于涉及 Alt-Svc HTTP标头的两步发现过程以
及HTTP / 2连接不能简单地“升级”到HTTP / 3的事实,因为后者使用UDP。
但是,可能成为问题的是测试和验证您是否使用了正确的配置以及协议是否按
预期使用。这在生产中是正确的,但在本地设置中尤其如此。因此,我预计大
多数人将继续运行HTTP / 2(甚至HTTP / 1.1)开发服务器,仅在以后的部署
阶段切换到HTTP / 3。然而,即便如此,使用当前一代工具验证协议性能也并非
易事。
工具和测试# (↦ #Tools-And-Testing)
与许多主要服务器的情况一样,最流行的Web性能测试工具的制造商从一开始
就没有跟上HTTP / 3的步伐。因此,截至2021年7月,很少有工具对新协议提供
专门支持,尽管它们在一定程度上支持它。
谷歌灯塔# (↦ #GOOGLE-LIGHTHOUSE)
网页测试# (↦ #WEBPAGETEST)
其次,有WebPageTest (↦ https://www.webpagetest.org/)。这个惊人的项目允许您从世
界各地的真实设备通过真实网络加载页面,它还允许您在顶部添加数据包级网
络仿真,包括数据包丢失等方面!因此,WebPageTest在概念上处于用于比较
HTTP / 2和HTTP / 3性能的主要位置。然而,虽然它确实已经可以通过新协议加
载页面,但HTTP / 3尚未正确集成到工具或可视化中。例如,目前没有简单的
方法可以通过QUIC强制页面加载,轻松查看实际使用情况,甚至查看QUIC握手
详细信息。在某些情况下,即使查看响应是使用HTTP / 3还是HTTP / 2也可能具
有挑战性。尽管如此,在四月份,我还是能够使用WebPageTest运行相当多的测
试,并看到HTTP / 3的实际运行,我现在将对此进行介绍。 Alt-Svc facebook.com
首先,我运行了 的默认测试,启用了“重复视图”选项。如上所述 (↦
https://www.smashingmagazine.com/2021/09/http3-practical-deployment-options-part3/#alt-svc),我
希望第一个页面加载使用HTTP / 2,这将包括响应标头。因此,重复视图应从一
开始就使用 HTTP/3。在Firefox版本89 (↦
https://www.webpagetest.org/result/210420_AiDcQS_8c1a37579b3b6d291868d0242abb26a1/)中,这或
多或少是发生的事情。但是,在查看单个响应时,我们看到即使在第一个页面
加载期间,Firefox也会切换到使用HTTP / 3而不是HTTP / 2!如图 2 所示,从
第 20 个资源开始会发生这种情况。这意味着Firefox在看到标头后立即建立新的
QUIC连接,并在成功后切换到该连接。如果您向下滚动到连接视图,它似乎还
显示Firefox甚至打开了两个QUIC连接:一个用于凭据的CORS请求,另一个用于
无CORS请求。这是可以预料到的,因为正如我们上面所讨论的 (↦
https://www.smashingmagazine.com/2021/09/http3-practical-deployment-options-part3/#what-does-it-
all-mean-2),即使对于HTTP / 2和HTTP / 3,浏览器也会由于安全问题而打开多个
all mean 2),即使对于HTTP / 2和HTTP / 3,浏览器也会由于安全问题而打开多个
连接。但是,由于 WebPageTest 在此视图中未提供更多详细信息,因此如果不
手动挖掘数据,则很难进行确认。查看重复视图(第二次访问),它首先直接
对第一个请求使用 HTTP/3,如预期的那样。 facebook.com Alt-Svc Alt-Svc
(↦ https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/7c3ef819-126d-
4140-98ab-2bdf5344854f/firefox-facebook.png)
接下来,对于Chrome (↦
https://www.webpagetest.org/result/210420_AiDcP0_6aeaac212f59298cf834ad30b4ec72e6/),我们看
到第一个页面加载的行为类似,尽管在这里Chrome已经打开了第10个资源,比
Firefox早得多。这里更不清楚的是,它是尽快切换,还是仅在需要新连接时切
换(例如,对于具有不同凭据的请求),因为与Firefox不同,连接视图似乎也
没有显示多个QUIC连接。对于重复视图,我们看到了一些更奇怪的事情。出乎
意料的是,Chrome也开始在那里使用HTTP / 2,仅在几次请求后才切换到
HTTP / 3!我还在其他页面上进行了一些 (↦
https://www.webpagetest.org/result/210420_BiDcXS_d2bca9bd9ddce71dfc7bc0618fe7ed11/) (↦
https://www.webpagetest.org/result/210420_AiDc7G_540eaf6f42de75ba9cdf2785528e36e9) 测试 (↦
https://www.webpagetest.org/result/210420_AiDcBR_84d6accab1a208c4eb801df6ef689e5e),以确认
这确实是一致的行为。这可能是由于以下几件事:这可能只是Chrome的当前政
策,可能是Chrome“比赛”了 (↦ https://www.smashingmagazine.com/2021/09/http3-practical-
deployment-options-part3/#alt-svc)TCP和QUIC连接并且TCP最初获胜,或者可能是由于
某种原因,第一个视图中的缓存未被使用。可悲的是,在这一点上,没有简单
的方法来确定问题到底是什么(以及它是否可以修复)。 Alt-Svc
我在这里注意到的另一个有趣的事情是明显的连接合并行为。如上
所述 (↦ https://www.smashingmagazine.com/2021/09/http3-practical-deployment-
options-part3/#http2),HTTP/2 和 HTTP/3 都可以重用连接,即使它们转
到其他主机名,以防止主机名分片的缺点。但是,如图 3 所示,
WebPageTest 报告,对于此 Facebook 负载,连接合并通过 HTTP/3 用于
和 ,而不是通过 HTTP/2 使用(因为 Chrome 为第二个域打开辅助连
接)。然而,我怀疑这是WebPageTest中的一个错误,因为和解析为
不同的IP,因此无法真正合并。 facebook.com fbcdn.net facebook.com
fbcnd.net
(↦ https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/dc343577-ecc6-
4d09-9674-8ce22d290870/chrome-facebook-connection.png)
注意:正如我们所看到的,获得“真正的”HTTP / 3有时可能很困难。幸运的是,
特别是对于Chrome,我们还有其他选项可用于以命令行参数的形式测试QUIC和
HTTP / 3。
在WebPageTest的“Chromium”选项卡的底部,我使用了以下命令行选项:
on=www.facebook.com:443,static.xx.fbcdn.net:443
该测试的 (↦
https://www.webpagetest.org/result/210420_AiDcY7_ddae6dc06c438d83bb8625cf52951041)结果表
明,这确实从一开始就强制进行QUIC连接,即使在第一个视图中也是如此,从
而绕过了该过程。有趣的是,您会注意到我必须将两个主机名传递给 。当然,
在我没有打开的版本中 (↦
https://www.webpagetest.org/result/210420_BiDcHG_df3438e0dde2f5ea02fc1f865e4e43b8),Chrome
仍然首先打开了与域的HTTP / 2连接,即使在重复视图中也是如此。因此,您需
要手动指示所有QUIC来源才能使其正常工作! Alt-Svc --origin-to-force-quic-on
fbcnd.net
甚至从这几个例子中,我们可以看到,浏览器在实践中实际使用HTTP / 3的方式
有很多事情。似乎他们甚至在初始页面加载期间切换到新协议,尽快或需要新
连接时放弃HTTP / 2。因此,不仅很难获得完整的HTTP / 3负载,而且很难在支
持两者的设置上获得纯HTTP / 2负载!由于WebPageTest尚未显示太多HTTP / 3
或QUIC元数据,因此弄清楚发生了什么可能具有挑战性,并且您也不能从表面
上信任工具和可视化。
因此,如果您使用WebPageTest,则需要仔细检查结果以确保实际使用了哪些协
议。因此,我认为这意味着现在真正测试HTTP / 3性能还为时过早(特别是将
其与HTTP / 2进行比较还为时过早)。并非所有服务器和客户端都实现了所有协
议功能,这一事实加强了这一信念。由于WebPageTest还没有简单的方法来显示
是否使用了0-RTT等高级方面,因此很难知道您实际测量的内容。对于HTTP / 3
优先级功能 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-improvements-
part2/#packet-loss-resilienceg)尤其如此,该功能尚未在所有浏览器中正确实现,并且
许多服务器也缺乏完全支持。由于优先级可能是推动Web性能的一个主要方面
(↦ https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/),因此在不确保至少
此功能正常工作的情况下将HTTP / 3与HTTP / 2进行比较是不公平的(对于两种
协议!不过,这只是一个方面,因为我的研究表明QUIC实现之间的差异有多大
(↦ https://qlog.edm.uhasselt.be/epiq/files/QUICImplementationDiversity_Marx_final_11jun2020.pdf)。
如果您自己进行任何此类比较(或者如果您阅读了此类比较的文章),请100%
确定您已经检查了实际发生的事情。
最后,还要注意,其他更高级的工具(或数据集,如惊人的HTTP Archive (↦
https://httparchive.org/))通常基于WebPageTest或Lighthouse(或使用类似的方
法),所以我怀疑我在这里的大多数评论将广泛适用于大多数Web性能工具。
即使对于那些在未来几个月内宣布支持HTTP / 3的工具供应商 我也会有点怀
即使对于那些在未来几个月内宣布支持HTTP / 3的工具供应商,我也会有点怀
疑,并会验证他们是否真的做对了。但是,对于某些工具,情况可能更糟。例
如,Google的PageSpeed Insights今年只得到了HTTP / 2支持 (↦
https://developers.google.com/speed/docs/insights/release_notes),所以我不会等待HTTP / 3很
快到来。
正如上面的讨论所示,此时仅使用Lighthouse或WebPageTest来分析HTTP / 3行
为可能很棘手。幸运的是,其他较低级别的工具可以帮助解决这个问题。首
先,优秀的Wireshark (↦ https://www.wireshark.org/)工具对QUIC有先进的支持,它也
可以通过实验来剖析HTTP/3。这使您可以观察哪些 QUIC 和 HTTP/3 数据包实际
上正在通过网络传输。但是,为了使其正常工作,您需要获取给定连接的TLS解
密密钥,大多数实现(包括Chrome和Firefox)都允许您使用环境变量 (↦
https://www.steffr.ch/inspect-ssl-tls-traffic-from-chrome-firefox-curl-with-wireshark-no-mitm/)提取这
些密钥。虽然这对某些事情很有用,但真正弄清楚发生了什么,特别是对于更
长的连接,可能需要大量的手动工作。您还需要对协议的内部工作原理有非常
深入的了解。 SSLKEYLOGFILE
幸运的是,还有第二个选项,qlog和qvis。qlog (↦ https://github.com/quicwg/qlog) 是一
种基于 JSON 的日志记录格式,专门用于 QUIC 和 HTTP/3,大多数 QUIC 实现都
支持这种格式。qlog不是查看通过线路传输的数据包,而是直接在客户端和服务
器上捕获此信息,这允许它包含一些其他信息(例如,拥塞控制详细信息)。
通常,您可以在使用环境变量启动服务器和客户端时触发 qlog 输出。(请注
意,在 Firefox 中,您需要设置 network.http.http3.enable_qlog (↦
https://bugzilla.mozilla.org/show_bug.cgi?id=1649495)首选项。苹果设备和Safari使用
QUIC_LOG_DIRECTORY (↦ https://developer.apple.com/videos/play/wwdc2021/10094/)。Chrome 还不
支持 qlog。 QLOGDIR
这一切意味着什么?# (↦ #WHAT-DOES-IT-ALL-MEAN-3)
仅依赖高级指标是非常危险的,因为这些指标可能会被大量因素所扭曲(例如
不切实际的网络仿真,客户端或服务器上缺乏功能,仅部分使用HTTP / 3等)。
即使一切都做得更好,正如我们在第2部分中 (↦
https://www.smashingmagazine.com/2021/08/http3-performance-improvements-part2/#conclusion)所
看到的,在大多数情况下,HTTP / 2和HTTP / 3之间的差异也可能相对较小,这
使得在没有有针对性的HTTP / 3支持的情况下从高级工具中获取必要的信息变得
更加困难。
结论和要点# (↦ #Conclusion-And-Takeaways)
亲爱的读者,如果您已经阅读了完整的三部分系列并在这里制作,我向您致
敬!即使您只阅读了几节,我也感谢您对这些新的令人兴奋的协议的兴趣。现
在,我将总结本系列的主要内容,为未来几个月和一年提供一些关键建议,最
后为您提供一些其他资源,以防您想了解更多信息。
总结# (↦ #SUMMARY)
建议# (↦ #RECOMMENDATIONS)
从上面的摘要来看,我似乎在提出反对使用QUIC或HTTP / 3的有力论据。然
而,这与我想说的完全相反。
首先,正如第 2 部分 (↦ https://www.smashingmagazine.com/2021/08/http3-performance-
improvements-part2/#conclusion)末尾所讨论的,即使您的“普通”用户可能不会遇到重
大的性能提升(取决于您的目标市场),但您的很大一部分受众可能会看到令
人印象深刻的改进。0-RTT 可能只保存一次往返行程,但对于某些用户来说,
这仍然意味着几百毫秒。连接迁移可能无法持续保持快速下载,但它肯定会帮
助那些试图在高速列车上获取该PDF的人。电缆上的数据包丢失可能是突发的,
但无线链路可能会从QUIC的线头阻塞删除中受益更多。更重要的是,这些用户
通常是那些通常会遇到产品性能最差的用户,因此受其影响最大。如果你想知
道为什么这很重要,请阅读克里斯·扎卡里亚斯(Chris Zacharias)著名的网络表
演轶事 (↦ https://blog.chriszacharias.com/page-weight-matters)。
其次,随着时间的推移,QUIC和HTTP / 3只会变得更好,更快。版本1专注于
完成基本协议,保留更高级的性能功能供以后使用。因此,我觉得现在开始投
资协议是值得的,以确保您可以在它们可用时使用它们和新功能以达到最佳效
果。考虑到协议的复杂性及其部署方面,最好给自己一些时间来熟悉它们的怪
癖。即使您还不想弄脏自己的手,几家主要的CDN提供商也提供成熟的“翻转开
关”HTTP / 3支持(特别是Cloudflare和Fastly)。如果你使用的是CDN,我很难
找到不尝试的理由(如果你关心性能,你真的应该这样做)。
因此,虽然我不会说尽快开始使用QUIC和HTTP / 3至关重要,但我确实觉得已
经有很多好处 而且它们只会在未来增加