HTTP/2&文件下载

HTTP/2 & File Download

我们提供文件托管解决方案。我们的客户是最终用户,他们通过 HTTP 1.1 协议访问我们的服务器并下载文件。这些客户端基本上是软件系统或 CDN,它们使用软件库下载我们的文件。没有人类用户访问我们的系统。我们还提供使用 HTTP/1.1 range-header 等进行部分文件下载的选项。客户端系统还使用多线程通过跨块拆分来下载大文件。

我想看看如果我们向我们的服务器开放 HTTP/2.0 协议是否会有真正的好处?由于我们的客户端系统已经能够使用多线程来下载我们的文件,HTTP/2.0 多路复用是否会带来任何实际好处?

谢谢

HTTP/2 文件下载比 HTTP/1.1 慢一点,主要原因有两个:帧开销和 flow control.

在 HTTP/1.1 中,如果您使用 Content-Length 分隔下载,则下载的唯一字节是内容字节。 然而,在 HTTP/2 中,每个 DATA 帧携带 9 个额外字节作为帧头。在 16384 字节的正常最大帧大小下,这是一个很小的开销,但它存在。

可能导致速度下降的更大因素是 HTTP/2 流量控制。 客户端一定要放大默认session和流控windows,默认都是65535字节。

HTTP/2的工作方式是服务器为每个HTTP/2session(连接)保留一个sendwindow以及 session 中的每个流。 下载开始时,服务器有权仅发送发送 window 允许的字节数,用于该流或 session,以先用完者为准。然后它必须等待客户端发送 WINDOW_UPDATE 帧,补充流和 session 流量控制 windows,告诉服务器客户端已准备好接收更多数据。

对于较小的 windows(例如默认机制),由于客户端和服务器之间的网络延迟,此机制可能会降低下载性能,尤其是在天真地实施时。 服务器在等待客户端发送 WINDOW_UPDATE 以便服务器可以发送更多数据的大部分时间将停止。

多路复用起着双重作用。虽然它允许同时启动许多文件的下载(可能比 HTTP/1.1 更多的文件,这可能受到它只能打开较少数量的连接这一事实的限制),数据也是如此为每个流下载有助于减少 session 发送 window。每个流可能仍然有一个未耗尽的发送 window(因此它可以发送更多数据),但是 session window 已耗尽,因此服务器必须停止。流相互竞争以消耗 session 发送 window。服务器实现也很重要,因为它必须正确地交错来自多个流的帧。

话虽如此,HTTP/2 仍然有可能实现与 HTTP/1.1 的同等水平,前提是您拥有相当先进的客户端和服务器实现,并且您有足够的调谐旋钮来控制关键参数。

理想情况下,在客户端:

  • 能够控制 session 和流初始流量控制 windows
  • 一个很好的实现,它在服务器仍在下载时向服务器发送 WINDOW_UPDATE 帧,这样服务器就不会停止;这可能需要 self-tuning 功能,具体取决于 bandwidth-delay product(类似于 TCP 所做的)

理想情况下,在服务器上:

  • 能够正确交错来自多个相同流的帧 session(例如,避免下载第一个流的所有帧,然后是第二个流的所有帧,等等,而是下载一个帧第一个流后跟第二个流的一帧,然后是第一个流的一帧,等等)

[免责声明,我是 Jetty]

的 HTTP/2 维护者

Jetty 9.4.x 支持上述所有功能,因为我们与社区和客户合作以确保 HTTP/2 下载速度尽可能快。

我们在服务器上实现了适当的交错,Jetty 的 HttpClientHTTP2Client 分别提供了高级和低级 API 来处理 HTTP 和 HTTP/2 请求。流量控制在 BufferingFlowControlStrategy 中实现,并允许在发送 WINDOW_UPDATE 帧时进行调整(尽管尚未动态)。 客户端还可以选择配置初始流量控制 windows。 Jetty 中的所有内容都是可插拔的,因此您可以编写更高级的流量控制策略。

即使您不使用 Java 或 Jetty,也请务必剖析(或编写)您在客户端和服务器上使用的库,以便它们提供上述功能。

最后,您需要尝试测量;通过适当的 HTTP/2 实施和配置,多路复用效果应该发挥作用,从而增加并行度并减少客户端和服务器上的资源利用率,这样您将比 HTTP/1.1.