HTTP2.0 的出现,不仅极大的提高 Web 性能,也减少前端工程师对于前端优化的工作。奈何本人水平有限,暂时只能依靠几篇文章对 HTTP2.0 有个粗浅的认识。本文属于知识汇总,有些文字照抄了部分博文,如果有侵犯,立即删除。

二进制分帧

二进制分帧

在应用层与传输层之间增加一个二进制分帧层,以此达到“在不改动 HTTP 的语义,HTTP 方法、状态码、URI 及首部字段的情况下,突破 HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量。”

在二进制分帧层上,HTTP2.0 会将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 Headers 帧,而我们的 request body 则封装到 Data 帧里面。

插播一些基础概念:

  • 流:已建立的连接上的双向字节流。
  • 消息:与逻辑消息对应的完整的一系列数据帧。
  • 帧:HTTP2.0 通信的最小单位,每个帧包含首部,至少也会标识出当前帧所属的流。

流、帧、消息

压缩头部

压缩头部

HTTP2.0 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;通信期间几乎不会改变的通用键-值对(用户代理、可接受的媒体类型,等等)只需发送一次。

事实上,如果请求中不包含首部(例如对同一资源的轮询请求),那么首部开销就是零字节。此时所有首部都自动使用之前请求发送的首部。

如果首部发生变化了,那么只需要发送变化了数据在 Headers 帧里面,新增或修改的首部帧会被追加到“首部表”。首部表在 HTTP2.0 的连接存续期内始终存在,由客户端和服务器共同渐进地更新。

多路复用(Multiplexing)

 HTTP2.0 多路复用Multiplexing

对于 HTTP1.1,浏览器通常最多有链接的限制,即使开启多个链接,也需要付出不小的代价。而多路复用允许同时通过单一的 HTTP2.0 连接发起多重的“请求-响应”消息。

在共享的连接上同时发送和请求和响应

客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。注意,同一链接上有多个不同方向的数据流在传输。客户端可以一边乱序发送 stream,也可以一边接收者服务器的响应,而服务器那端同理。

也就是说, HTTP2.0 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。就好比,我请求一个页面 http://www.qq.com 。页面上所有的资源请求都是客户端与服务器上的一条 TCP 上请求和响应的!

请求优先级

既然所有资源都是并行交错发送,会不会出现这样的情况 浏览器明明在等关键的 CSS 和 JS,你 TMD 的服务器还在发送图片

每个 HTTP2.0 流里面有个优先值,这个优先值确定着客户端和服务器处理不同的流采取不同的优先级策略,高优先级的流都应该优先发送,但又不会绝对的。绝对地准守,可能又会引入首队阻塞的问题:高优先级的请求慢导致阻塞其他资源交付。分配处理资源和客户端与服务器间的带宽,不同优先级的混合也是必须的。

所以就不会出现如上描述的这种情况了。

服务器推送

服务器推送

在 HTTP2.0 中,服务器推送是指在客户端请求之前发送数据的机制。如果一个请求是由你的主页发起的,服务器很可能响应主页内容、logo 以及样式表,因为它知道客户端会用到这些东西。这相当于在一个 HTML 文档内集合了所有的资源,不过与之相比,服务器推送有一个很大的优势:可以缓存!

当然这同时也是它的一个缺点,如果客户端已经缓存了数据,此时会产生不必要的冗余。这也是为什么推荐服务器提示(Server Hints)的原因。

服务器提示(Server Hints)

服务器提示可以先于客户端检测到将要请求的资源,提前通知客户端,服务器不发送所有资源的实体,它只发送资源的 URL。客户端接到提示后进一步验证之前的缓存,如果发现需要这些资源,则正式发起请求。服务器提示对 HTTP2.0 来说兴许不是最新的,但非常值得在这里顺便一提,因为它没有上文提到的服务器推送冗余的缺点。

服务器提示是通过 HTTP Link header 和与已实现的 link prefetching 语义重叠的部分来实现的。举个例子,一个HTTP Link header 看起来是这样的:

Link: <https://example.com/images/large-background.jpg>; rel=prefetch

如果 HTML 文档的 head 标签中有一个 prefetch link 标签,不需要在服务端有额外的实现,举个例子:

<link rel="prefetch" href="https://example.com/images/large-background.jpg">

HTTP2.0 对前端优化带来的影响:

  • 因为“所有的 HTTP2.0 的请求都在一个 TCP 链接上”,“资源合并减少请求”,比如 CSS Sprites,多个 JS 文件、CSS 文件合并等手段没有效果,或者说没有必要。
  • 因为“多路复用”,采用“cdn1.cn,cdn2.cn,cdn3.cn,打开多个 TCP 会话,突破浏览器对同一域名的链接数的限制”的手段是没有必要的。因为因为资源都是并行交错发送,且没有限制,不需要额外的多域名并行下载。
  • 因为“服务器推送”,内嵌资源的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)。

参考文章

以上。