http2flowControl

HTTP2的流控制

协议中怎么说?

协议中对流量控制的目的和特点有清晰的描述

Flow control (Section 5.2)helps to ensure that only data that can be used by a receiver is transmitted.

流量控制有助于确保只传播接受者需要使用的数据数据。

HTTP/2 provides for flow control through use of the WINDOW_UPDATE frame (Section 6.9).

HTTP/2 利用流来实现多路复用,这引入了对 TCP 连接的使用争夺,会造成流被阻塞。流量控制方案确保在同一连接上的多个流之间不会造成破坏性的干扰。流量控制会用于各个独立的流,也会用于整个连接。

HTTP/2 通过使用 WINDOW_UPDATE 帧来进行流量控制。

HTTP/2「流」的流量控制的目标是:在不改变协议的情况下允许使用多种流量控制算法。

HTTP/2 的流量控制具有以下特征:

  • 流量控制是特定于一个连接的。每种类型的流量控制都是在单独的一跳的两个端点之间的,并不是在整个端到端的路径上的。(这里的一跳指的是 HTTP 连接的一跳,而不是 IP 路由的一跳)
  • 流量控制是基于 WINDOW_UPDATE帧的。接收方公布自己打算在每个流以及整个连接上分别接收多少字节。这是一个以信用为基础的方案。
  • 流量控制是有方向的,由接收者全面控制。接收方可以为每个流和整个连接设置任意的窗口大小。发送方必须尊重接收方设置的流量控制限制。客户方、服务端和中间代理作为接收方时都独立地公布各自的流量控制窗口,作为发送方时都遵守对端的流量控制设置。
  • 无论是新流还是整个连接,流量控制窗口的初始值是 65535 字节。
  • 帧的类型决定了流量控制是否适用于帧。目前,只有 DATA 帧服从流量控制,所有其它类型的帧并不消耗流量控制窗口的空间。这保证了重要的控制帧不会被流量控制阻塞。
  • 流量控制不能被禁用。
  • HTTP/2 只定义了 WINDOW_UPDATE 帧的格式和语义,并没有规定接收方如何决定何时发送帧、发送什么样的值,也没有规定发送方如何选择发送包。具体实现可以选择任何满足需求的算法。

    现实中遇到的问题

    最近在工作中主要从事于公司统一的推送系统的研发,其中有一点是要给大量的额IOS用户推送消息,而Apple提供的推送接口正是基于Http2协议的。

从监控中发现经常会有及其中堆积大量的gorutine的问题,后用pprof拉取之后发现大量gorutine卡在了http2的流量控制上。

后使用多个http2Client,根据返回值更新权重的方式来轮训client解决了这个问题。

进一步探究

  1. 发送端保有一个流量控制窗口(window)初始值。初始值的设定请参考 SETTING 帧的 SETTINGS_INITIAL_WINDOW_SIZE

  2. 发送端每发送一个 DATA 帧,就把 window 递减,递减量为这个帧的大小。如果当前 window 小于帧大小,那么这个帧就必须被拆分到不大于 window,如果 window 等于 0,就不能发送任何帧

  3. 接收端可以发送 WINDOW_UPDATE 帧给发送端,发送端以帧内指定的 Window Size Increment 作为增量,加到 window 上