有人可以解释一下与 HTTP/2 相关的多路复用以及它是如何工作的吗?
简而言之,多路复用允许您的浏览器在同一连接上一次触发多个请求,并以任何顺序接收请求。
现在对于更复杂的答案......
当你加载一个网页时,它会下载 HTML 页面,它认为它需要一些 CSS、一些 JavaScript、大量图像……等等。
在 HTTP/1.1 下,您一次只能在 HTTP/1.1 连接上下载其中一个。因此,您的浏览器会下载 HTML,然后请求 CSS 文件。当它返回时,它会询问 JavaScript 文件。当它返回时,它会要求第一个图像文件......等等。HTTP/1.1 基本上是同步的——一旦你发送一个请求,你就会被卡住,直到你得到响应。这意味着大多数时候浏览器并没有做太多事情,因为它已经触发了一个请求,正在等待响应,然后触发另一个请求,然后等待响应......等等。当然复杂的网站有许多 JavaScript 确实需要浏览器进行大量处理,但这取决于正在下载的 JavaScript,因此,至少在开始时,继承到 HTTP/1.1 的延迟确实会导致问题。通常服务器是’
因此,当今网络上的主要问题之一是在浏览器和服务器之间发送请求时的网络延迟。它可能只有几十或几百毫秒,这可能看起来不多,但它们加起来通常是网页浏览中最慢的部分 - 特别是当网站变得更加复杂并且需要额外的资源(因为他们正在获得)和互联网访问时越来越多地通过移动设备(延迟比宽带慢)。
举个例子,假设在 HTML 本身加载后,您的网页需要加载 10 个资源(按照今天的标准,这是一个非常小的站点,因为 100 多个资源很常见,但我们会保持简单并使用这个例子)。假设每个请求需要 100 毫秒才能通过 Internet 传输到 Web 服务器并返回,并且任一端的处理时间可以忽略不计(为简单起见,我们在此示例中假设为 0)。由于您必须一次发送每个资源并等待响应,因此下载整个站点需要 10 * 100ms = 1,000ms 或 1 秒。
为了解决这个问题,浏览器通常会打开多个到 Web 服务器的连接(通常为 6 个)。这意味着浏览器可以同时触发多个请求,这要好得多,但代价是必须设置和管理多个连接的复杂性(这会影响浏览器和服务器)。让我们继续前面的例子,假设有 4 个连接,为了简单起见,假设所有请求都是相等的。在这种情况下,您可以在所有四个连接中拆分请求,因此两个将有 3 个资源要获取,两个将有 2 个资源来获取总共十个资源 (3 + 3 + 2 + 2 = 10)。在这种情况下,最坏的情况是 3 个轮次或 300 毫秒 = 0.3 秒 - 一个很好的改进,但这个简单的示例不包括设置这些多个连接的成本,
HTTP/2 允许您在 同一时间发送多个请求 连接 - 因此您无需按照上述打开多个连接。所以你的浏览器可以说“给我这个 CSS 文件。给我那个 JavaScript 文件。给我 image1.jpg。给我 image2.jpg……等等。” 充分利用一个单一的连接。这具有明显的性能优势,即不会延迟发送那些等待空闲连接的请求。所有这些请求以(几乎)并行的方式通过 Internet 到达服务器。服务器响应每个人,然后他们开始返回。事实上,它甚至比这更强大,因为 Web 服务器可以以任何感觉的顺序响应它们并以不同的顺序发送回文件,甚至将请求的每个文件分解成碎片并将文件混合在一起。线头阻塞问题)。然后,Web 浏览器的任务是将所有部分重新组合在一起。在最好的情况下(假设没有带宽限制 - 见下文),如果所有 10 个请求几乎同时并行触发,并由服务器立即响应,这意味着您基本上有一个往返或 100 毫秒或 0.1 秒,下载所有 10 个资源。这没有 HTTP/1.1 的多个连接的缺点!随着每个网站上资源的增长,这也更具可扩展性(目前浏览器在 HTTP/1.1 下最多可打开 6 个并行连接,但随着网站变得更加复杂,这是否应该增长?)。
该图显示了差异,并且还有一个动画版本。
注意:HTTP/1.1 确实有流水线的概念,它也允许同时发送多个请求。然而,它们仍然必须按照被请求的顺序全部返回,因此远不如 HTTP/2,即使在概念上是相似的。更不用说浏览器和服务器对它的支持太差了,以至于很少使用它。
以下评论中强调的一件事是带宽如何影响我们。当然,您的 Internet 连接受到您可以下载的数量的限制,而 HTTP/2 并没有解决这个问题。因此,如果上面示例中讨论的这 10 个资源都是海量打印质量的图像,那么它们的下载速度仍然很慢。但是,对于大多数 Web 浏览器来说,带宽比延迟更不是问题。因此,如果这十个资源是小项目(尤其是像 CSS 和 JavaScript 这样的文本资源,可以压缩成很小的内容),这在网站上很常见,那么带宽就不是真正的问题 - 通常是资源的绝对数量问题和 HTTP/2 看起来解决了这个问题。这也是为什么在 HTTP/1.1 中使用串联作为另一种解决方法的原因,例如,所有 CSS 通常都被连接到一个文件中:HTTP/2 下的反模式——尽管也有人反对完全废除它)。
把它作为一个现实世界的例子:假设你必须从商店订购 10 件商品以便送货上门:
带有一个连接的 HTTP/1.1 意味着您必须一次订购一个,并且在最后一个到达之前您不能订购下一个。您可以理解,完成所有事情需要数周时间。
具有多个连接的 HTTP/1.1 意味着您可以同时拥有(有限)数量的独立订单。
带有流水线的 HTTP/1.1 意味着您可以一个接一个地请求所有 10 个项目而无需等待,但随后它们都会按照您要求的特定顺序到达。如果一件商品缺货,那么您必须等待,然后才能收到之后订购的商品——即使这些后来的商品实际上有货!这有点好,但仍然会延迟,假设大多数商店都不支持这种订购方式。
HTTP/2 意味着您可以按任何特定顺序订购商品 - 没有任何延迟(类似于上面)。商店将在它们准备好时发送它们,因此它们可能会以与您要求的顺序不同的顺序到达,并且它们甚至可能会拆分商品,以便该顺序的某些部分首先到达(比上面的要好)。最终,这应该意味着您 1) 总体上更快地获得所有东西,并且 2) 可以在每个项目到达时开始处理它(“哦,这并不像我想象的那么好,所以我可能想订购其他东西或者代替” )。
当然,您仍然受到邮递员面包车大小(带宽)的限制,因此如果当天已经满员,他们可能不得不将一些包裹留在分拣办公室直到第二天,但与此相比,这几乎不是问题延迟实际发送和返回订单。大多数网络浏览都涉及来回发送小字母,而不是大包。
希望有帮助。