介绍:开篇吹一波阿里云性能测试服务PTS。PTS已于2021年5月推出对HTTP2协议的支持(底层依赖httpclient5)。当使用HTTP1.1或HTTP2协议时,由与服务器协商的结果决定。作者:冯奇先来一波阿里云性能测试服务PTS[1]。PTS已于2021年5月推出对HTTP2协议的支持(底层依赖httpclient5),压力测试时将通过与服务端协商的结果。决定使用HTTP1.1还是HTTP2协议。背景写这篇文章的缘由是某天有个客户来找我们问我们不支持HTTP2,因为他在XX云上购买了两个域名,其中一个启用了HTTP2,在PTS压力测试的时候,支持HTTP2的接口总是报错:一开始怀疑是HTTP2支持的问题。通过在本地强制使用HTTP2协议,访问淘宝首页,发现没有问题。在强制使用HTTP1.1协议的情况下,本地的Postman、curl、压测引擎都可以正常访问网页,发现问题大概率是在PTS引擎端。通过本地调试,发现在请求URL时客户端窗口大小被调整为大于2^32-1。那么就趁着这个机会看看这里的窗口大小指的是什么吧。HTTP2流量控制说到windows,就不得不提到HTTP2相较于HTTP1.1所支持的新特性:流量控制(FlowControl)。其实HTTP1.1是靠TCP在传输层的滑动窗口来实现流量控制的,为什么呢?HTTP2是否需要在应用层再做一个流量控制?原因是HTTP2引入了流和多路复用,通过流量控制可以达到多流协同的效果。流量控制的一些基本概念:流量控制是针对连接的,不是针对端到端的,而是针对两端的每一跳;主要是指在有proxy的情况下,agent与两端之间存在流控流程,控制基于WINDOW_UPDATE帧,接收方可以通过流控来控制发送方的速度。流量控制可以作用于流和连接。对于连接和所有新打开的流,默认流量控制窗口大小为65535。最大值为2^32-1。无法禁用流量控制。为了方便理解,我们简单罗列一下HTTP2帧的类型:ThestreamRST_STREAM:强制结束某个流,只用于取消一端的流,不适用于正常流的结束向远端发送PING,远端必须返回PINGGOAWAY:用于某个端到端的连接WINDOW_UPDATE:更新流量控制窗口的大小CONTINUATION:如果headers太大,单个HEADERS帧是携带困难,通过这个帧头发送一个额外的HEADERS帧接下来我们重点关注与流控相关的帧,主要是SETTING和WINDOW_UPDATE。当连接建立后,对方的窗口大小会通过SETTINGS框进行调整。之后,在传输过程中,窗口大小会随着数据的发送而逐渐减小。小直到收到对方发送的WINDOW_UPDATE帧,从而更新窗口大小。SETTINGS帧主要包含以下内容:SETTINGS_HEADER_TABLE_SIZE:HPACK(一种头部压缩算法)头部表的最大长度,默认值为4096SETTINGS_ENABLE_PUSH:客户端发送给服务器的配置,如果设置为true,客户端将允许服务器推送响应,默认值trueSETTINGS_MAX_CONCURRENT_STREAMS:同时打开的最大流数,通常表示可以同时响应的请求数,默认为无限制的最大长度默认不限制对端可以接受的头列表。流量控制的实现如上所述。每发送一批数据帧,窗口大小就会减小。需要注意的是流量控制只针对DATA帧。前面说到流控既可以作用于stream也可以作用于connection,那么它是如何实现的呢?connection的流控与上面流的流控逻辑类似。每发送一个DATA帧,connection和stream窗口都会减少,但不同的是WINDOW_UPDATE要么单独作用于stream,要么单独作用于connection(当streamid为0时,表示Actonconnection)。问题定位那么回到一开始的问题,我们以网址https://www.sysgeek.cn/为例。通过本地代码调试,我们发现最后出现异常的原因是在接收到WINDOW_UPDATE帧后,更新后的窗口大小值如果大于2^32-1,就会抛出异常:从这里的代码来看,它可以看出524288是当前窗口大小,delta是对方通知的WINDOW_UPDATE大小。通过分析发现524288这个值和默认值65535不一样,于是继续阅读Whenwasthisvaluechanged:发现是在收到SETTINGS命令后初始化窗口大小的时候修改的,但是这与RFC7540[2]的描述冲突(连接窗口大小只能在收到WINDOW_UPDATE后修改):因此,我们断定httpcore5的源代码存在bug。删除标记的代码行后,请求可以正常执行。不幸的是,在为httpcore5准备PR的过程中,我发现这个bug已经在commit中修复了。参考文献[1]PTS:https://help.aliyun.com/docum...[2]RFC7540:https://datatracker.ietf.org/...原文链接未经许可不得转载。
