上述每一点都可能对HTTP/2 连接的吞吐量和延迟性能造成不利影响。然而,除了这些局限性之外,实验表明一个TCP连接仍然是HTTP/2 基础上的最佳部署策略:
目前为止的测试表明,压缩和优先级排定带来的性能提升,已经超过了队首阻塞(特别是丢包情况下)造成的负面效果。
流量控制在同一个TCP连接上传输多个数据流,就意味着要共享带宽。标定数据流的优先级有助于按序交付,但只有优先级还不足以确定多个数据流或多个连接间的资源分配。为解决这个问题,HTTP/2 为数据流和连接的流量控制提供了一个简单的机制:
流量控制基于每一跳进行,而非端到端的控制;
流量控制基于窗口更新帧进行,即接收方广播自己准备接收某个数据流的多少字节,以及对整个连接要接收多少字节;
流量控制窗口大小通过WINDOW_UPDATE 帧更新,这个字段指定了流ID和窗口大小递增值;
流量控制有方向性,即接收方可能根据自己的情况为每个流乃至整个连接设置任意窗口大小;
流量控制可以由接收方禁用,包括针对个别的流和针对整个连接。
HTTP/2 连接建立之后,客户端与服务器交换SETTINGS 帧,目的是设置双向的流量控制窗口大小。除此之外,任何一端都可以选择禁用个别流或整个连接的流量控制。
上面这个列表是不是让你想起了TCP流量控制?应该是,这两个机制实际上是一样的。然而,由于TCP流量控制不能对同一条HTTP/2 连接内的多个流实施差异化策略,因此光有它自己是不够的。这正是HTTP/2 流量控制机制出台的原因。
HTTP/2 标准没有规定任何特定的算法、值,或者什么时候发送WINDOW_UPDATE 帧。因此,实现可以选择自己的算法以匹配自己的应用场景,从而求得最佳性能。
优先级可以决定交付次序,而流量控制则可以控制HTTP/2 连接中每个流占用的资源:接收方可以针对特定的流广播较低的窗口大小,以限制它的传输速度。
服务器推送HTTP/2 新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。换句话说,除了对最初请求的响应外,服务器还可以额外向客户端推送资源(如下图所示),而无需客户端明确地请求。
建立HTTP/2 连接后,客户端与服务器交换SETTINGS 帧,借此可以限定双向并发的流的最大数量。因此,客户端可以限定推送流的数量,或者通过把这个值设置为0而完全禁用服务器推送。
为什么需要这样一个机制呢?
通常的Web应用都由几十个资源组成,客户端需要分析服务器提供的文档才能逐个找到它们。那为什么不让服务器提前就把这些资源推送给客户端,从而减少额外的时间延迟呢?服务器已经知道客户端下一步要请求什么资源了,这时候服务器推送即可派上用场。事实上,如果你在网页里嵌入过CSS、JavaScript,或者通过数据URI嵌入过其他资源,那你就已经亲身体验过服务器推送了。
把资源直接插入到文档中,就是把资源直接推送给客户端,而无需客户端请求。在HTTP/2 中,唯一的不同就是可以把这个过程从应用中拿出来,放到HTTP协议本身来实现,而且还带来了如下好处:
客户端可以缓存推送过来的资源;
客户端可以拒绝推送过来的资源;
推送资源可以由不同的页面共享;
服务器可以按照优先级推送资源。
所有推送的资源都遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。
有了服务器推送后,HTTP 1.x时代的大多数插入或嵌入资源的做法基本上也就过时了。唯一有必要直接在网页中插入资源的情况,就是该资源只供那一个网页使用,而且编码代价不大;除此之外,所有应用都应该使用HTTP/2 服务器推送。
参考文章
https://hpbn.co/http2/
Web性能权威指南