HTTP/2:What's New in HTTP/2

最近在学习前端方面相关的知识,关于缓存涉及到HTTP/2的知识,之前的认知还停留在HTTP/1.x,所以花了点时间学习一下HTTP/2。

HTTP/2最主要的变化:

1.二进制分帧

2.请求/响应复用

3.报头压缩

4.流优先化

5.服务器推送

6.流控制

二进制分帧

在HTTP/1.x中,请求和响应报文格式如图:

HTTP 1.x 的采用的还是文本格式,而HTTP/2将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码。HTTP/2新的请求和响应如下图所示:

pic by https://developers.google.com

请求/响应复用

在 HTTP/1.x 中,如果客户端要想发起多个并行请求以提升性能,则必须使用多个 TCP 连接。但是浏览器为了控制资源,还会对单个域名TCP链接请求数量进行限制;在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,同一个域名下所有的连接只需要一个,消除了因多个 TCP 连接而带来的延时和内存消耗。

报头压缩

HTTP 1.1请求的大小变得越来越大,有时甚至会大于TCP窗口的初始大小,因为它们需要等待带着ACK的响应回来以后才能继续被发送。HTTP/2对消息头采用HPACK(专为http/2头部设计的压缩格式)进行压缩传输,能够节省消息头占用的网络的流量。

HTTP每一次通信都会携带一组头部,用于描述这次通信的的资源、浏览器属性、cookie等。为了减少这块的资源消耗并提升性能,HTTP/2对头部进行压缩。

HPACK 压缩上下文包含一个静态表和一个动态表:静态表在规范中定义,并提供了一个包含所有连接都可能使用的常用 HTTP 标头字段(例如,有效标头名称)的列表;动态表最初状态为空,将根据在特定连接内交换的值进行更新。因此,为之前未见过的值采用静态 Huffman 编码,并替换每一侧静态表或动态表中已存在值的索引,可以减小每个请求的大小。如图所示

上图中请求一发送了所有的头部字段,而在HTTP/2中第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销。

流优先化[引用google dev]

将 HTTP 消息分解为很多独立的帧之后,我们就可以复用多个数据流中的帧,客户端和服务器交错发送和传输这些帧的顺序就成为关键的性能决定因素。为了做到这一点,HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系:

可以向每个数据流分配一个介于 1 至 256 之间的整数。

每个数据流与其他数据流之间可以存在显式依赖关系。

数据流依赖关系和权重的组合让客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应。反过来,服务器可以使用此信息通过控制 CPU、内存和其他资源的分配设定数据流处理的优先级,在资源数据可用之后,带宽分配可以确保将高优先级响应以最优方式传输至客户端。

HTTP/2 内的数据流依赖关系通过将另一个数据流的唯一标识符作为父项引用进行声明;如果忽略标识符,相应数据流将依赖于“根数据流”。声明数据流依赖关系指出,应尽可能先向父数据流分配资源,然后再向其依赖项分配资源。换句话说,“请先处理和传输响应 D,然后再处理和传输响应 C。

共享相同父项的数据流(即,同级数据流)应按其权重比例分配资源。 例如,如果数据流 A 的权重为 12,其同级数据流 B 的权重为 4,那么要确定每个数据流应接收的资源比例,请执行以下操作:

将所有权重求和:

将每个数据流权重除以总权重:因此,数据流 A 应获得四分之三的可用资源,数据流 B 应获得四分之一的可用资源;数据流 B 获得的资源是数据流 A 所获资源的三分之一。我们来看一下上图中的其他几个动手示例:顺序为从左到右:

数据流 A 和数据流 B 都没有指定父依赖项,依赖于显式“根数据流”;A 的权重为 12,B 的权重为 4。因此,根据比例权重:数据流 B 获得的资源是 A 所获资源的三分之一。

数据流 D 依赖于根数据流;C 依赖于 D。因此,D 应先于 C 获得完整资源分配。权重不重要,因为 C 的依赖关系拥有更高的优先级。

数据流 D 应先于 C 获得完整资源分配;C 应先于 A 和 B 获得完整资源分配;数据流 B 获得的资源是 A 所获资源的三分之一。

数据流 D 应先于 E 和 C 获得完整资源分配;E 和 C 应先于 A 和 B 获得相同的资源分配;A 和 B 应基于其权重获得比例分配。

如上面的示例所示,数据流依赖关系和权重的组合明确表达了资源优先级,这是一种用于提升浏览性能的关键功能,网络中拥有多种资源类型,它们的依赖关系和权重各不相同。不仅如此,HTTP/2 协议还允许客户端随时更新这些优先级,进一步优化了浏览器性能。换句话说,我们可以根据用户互动和其他信号更改依赖关系和重新分配权重。

服务器推送

服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。

注意:

所有服务器推送数据流都由帧发起,表明了服务器向客户端推送所述资源的意图,并且需要先于请求推送资源的响应数据传输。这种传输顺序非常重要:客户端需要了解服务器打算推送哪些资源,以免为这些资源创建重复请求。满足此要求的最简单策略是先于父响应(即,帧)发送所有帧,其中包含所承诺资源的 HTTP 标头。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181129G0T85U00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券