HTTP/2逐跳流量控制是如何实现的?

How is HTTP/2 hop-by-hop flow control accomplished?

正如 spec 所说:

Flow control is specific to a connection. Both types of flow control are between the endpoints of a single hop and not over the entire end-to-end path.

并且在6.9 WINDOW_UPDATE

Both types of flow control are hop by hop, that is, only between the two endpoints. Intermediaries do not forward WINDOW_UPDATE frames between dependent connections. However, throttling of data transfer by any receiver can indirectly cause the propagation of flow-control information toward the original sender.

但这怎么可能呢?似乎要求所有中介都了解 h2h2c 协议,我有两个问题:

  1. HTTP/2 是一个相对较新的标准,我看到很多网站都启用了它(包括我的博客)。虽然我可以毫无问题地访问这些网站,但这是否意味着沿途的每个中间设备(如路由器和集线器等)已经实现了自己的 HTTP/2 堆栈和流量控制算法(因为 RFC7540 没有规定流量控制算法)?

  2. 大多数网站使用h2而不是h2c,后者对应用层数据进行加密。 HTTP/2的流量控制是由接收者发送WINDOW_UPDATE帧完成的,也是应用层数据,那么中间设备如何知道这些数据是什么?如果他们无法解密数据并看到 Window Size Increment 部分,他们如何在不转发 WINDOW_UPDATE 帧的情况下完成流量控制?

首先,进行一些更正。

令牌 h2c 指的是明文 HTTP/2(因此 h2c 中的 c)。在你的第二个项目符号中,你说大多数网站都使用它,但实际上很少有人这样做,因为浏览器没有实现它。绝大多数网站使用 h2.

令牌 h2 指的是加密的 h2c,或者等同于 h2c 通过 TLS。

当客户端和服务器协商说话 h2 时,客户端发送的字节被加密并一直加密传输到服务器。这意味着中介没有机会解密流量(谢谢)。

这里HTTP/2规范所指的"hop"就是客户端和服务器之间的整个网段。

然而,HTTP/2 规范需要是通用的,并且在定义 HTTP/2.

等有线协议时不必担心浏览器和 Web 服务器如何交互

想象这样一种情况,客户端使用 h2server1 执行 HTTP/2 请求,并且 server1 需要调用 server2 来完成请求,这次使用 h2c。例如,server1 可能是一个前端 "proxy",根据某种逻辑将请求转发到 "right" 后端服务器。

在这种情况下,您有 2 个跃点:客户端-服务器 1 和服务器 1-服务器 2。

每个跃点都应用自己的流量控制。

例如,假设客户端向服务器上传一个大文件。 通常,客户端流控制发送 window 很小,比如默认的 65535 个八位字节。在停止上传之前,客户端最多只能发送 65535 个八位字节。

这 65535 个八位字节由 server1 接收。现在 server1 成为客户端以便与 server2 通信。假设 server1 的客户端在与 server2 通信时配置了更小的流量控制 window,比如 16384 个八位字节。

在此示例中,server1 在 16384 个八位字节后停止上传到 server2,并且必须设法保留剩余的 65535-16384 个八位字节等待 server2 通知(通过WINDOW_UPDATE帧)上传的数据已被消耗。

server1的客户端收到来自server2的WINDOW_UPDATE时,它可以向server2发送更多数据;而且,它还必须决定是否向客户端发送一个 WINDOW_UPDATE(因为它的流量控制 window 和客户端 现在有额外的 16384 个八位字节的空间)或者再等一会儿。 例如,它可以向 server2 发送另一个 16384 个八位字节,并且只有在从 server2 接收到第二个 WINDOW_UPDATE 后才能决定向客户端发送 WINDOW_UPDATE(带有更新16384+16384 个八位字节)。

从上面的例子可以看出,client和server1之间的流量控制与server1server2之间的流量控制相关但独立。

您可能还想阅读 this answer 以了解有关流量控制策略实施的讨论。

这取决于hops/intermediaries的含义。

如果中间层位于较低级别(TCP 网关、NAT、交换机等),那么它们对 HTTP/2 是透明的,因为 HTTP/2 流量控制是端到端应用的HTTP/2 客户端和服务器之间。他们之间的个别跃点可能使用较低级别的流量控制机制。

如果您的中介是一个 HTTP 代理,那么基本上有两个单独的 HTTP 请求在进行,每个请求都应用它自己的流量控制。代理应用程序有责任连接这些单独的跃点,同时保留流量控制属性。例如。通过不立即从第二个跃点读取整个响应,然后才将其转发到第一个跃点,而是通过流式传输合适的数据块。

在 HTTP 代理的情况下,您甚至会遇到将 HTTP/1.1 代理到 HTTP/2 的情况,反之亦然。在这些情况下,他们的代理将使用 HTTP/2 流量控制机制来保证对该跳的流量控制,并使用 TCP 流量控制来提供对另一跳的流量控制。如果协议类型被正确地封装在代理应用程序中(这意味着它将提供尊重 RequestResponse 类型的流控制的流操作)那么代理不同协议类型之间的流不应该太难的。