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.
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.
但这怎么可能呢?似乎要求所有中介都了解 h2
或 h2c
协议,我有两个问题:
HTTP/2 是一个相对较新的标准,我看到很多网站都启用了它(包括我的博客)。虽然我可以毫无问题地访问这些网站,但这是否意味着沿途的每个中间设备(如路由器和集线器等)已经实现了自己的 HTTP/2 堆栈和流量控制算法(因为 RFC7540 没有规定流量控制算法)?
大多数网站使用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 服务器如何交互
想象这样一种情况,客户端使用 h2
向 server1
执行 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
之间的流量控制与server1
和server2
之间的流量控制相关但独立。
您可能还想阅读 this answer 以了解有关流量控制策略实施的讨论。
这取决于hops/intermediaries的含义。
如果中间层位于较低级别(TCP 网关、NAT、交换机等),那么它们对 HTTP/2 是透明的,因为 HTTP/2 流量控制是端到端应用的HTTP/2 客户端和服务器之间。他们之间的个别跃点可能使用较低级别的流量控制机制。
如果您的中介是一个 HTTP 代理,那么基本上有两个单独的 HTTP 请求在进行,每个请求都应用它自己的流量控制。代理应用程序有责任连接这些单独的跃点,同时保留流量控制属性。例如。通过不立即从第二个跃点读取整个响应,然后才将其转发到第一个跃点,而是通过流式传输合适的数据块。
在 HTTP 代理的情况下,您甚至会遇到将 HTTP/1.1 代理到 HTTP/2 的情况,反之亦然。在这些情况下,他们的代理将使用 HTTP/2 流量控制机制来保证对该跳的流量控制,并使用 TCP 流量控制来提供对另一跳的流量控制。如果协议类型被正确地封装在代理应用程序中(这意味着它将提供尊重 Request
和 Response
类型的流控制的流操作)那么代理不同协议类型之间的流不应该太难的。
正如 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.
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.
但这怎么可能呢?似乎要求所有中介都了解 h2
或 h2c
协议,我有两个问题:
HTTP/2 是一个相对较新的标准,我看到很多网站都启用了它(包括我的博客)。虽然我可以毫无问题地访问这些网站,但这是否意味着沿途的每个中间设备(如路由器和集线器等)已经实现了自己的 HTTP/2 堆栈和流量控制算法(因为 RFC7540 没有规定流量控制算法)?
大多数网站使用
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 服务器如何交互想象这样一种情况,客户端使用 h2
向 server1
执行 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
之间的流量控制与server1
和server2
之间的流量控制相关但独立。
您可能还想阅读 this answer 以了解有关流量控制策略实施的讨论。
这取决于hops/intermediaries的含义。
如果中间层位于较低级别(TCP 网关、NAT、交换机等),那么它们对 HTTP/2 是透明的,因为 HTTP/2 流量控制是端到端应用的HTTP/2 客户端和服务器之间。他们之间的个别跃点可能使用较低级别的流量控制机制。
如果您的中介是一个 HTTP 代理,那么基本上有两个单独的 HTTP 请求在进行,每个请求都应用它自己的流量控制。代理应用程序有责任连接这些单独的跃点,同时保留流量控制属性。例如。通过不立即从第二个跃点读取整个响应,然后才将其转发到第一个跃点,而是通过流式传输合适的数据块。
在 HTTP 代理的情况下,您甚至会遇到将 HTTP/1.1 代理到 HTTP/2 的情况,反之亦然。在这些情况下,他们的代理将使用 HTTP/2 流量控制机制来保证对该跳的流量控制,并使用 TCP 流量控制来提供对另一跳的流量控制。如果协议类型被正确地封装在代理应用程序中(这意味着它将提供尊重 Request
和 Response
类型的流控制的流操作)那么代理不同协议类型之间的流不应该太难的。