HTTP2是如何优化传输性能的
前言
HTTP2.0大幅度的提高了web性能,在HTTP1.1完全语意兼容的基础上,进一步减少了网络的延迟。实现低延迟高吞吐量。对于前端开发者而言,减少了优化工作。本文将重点围绕以下几点新特性的作用、工作过程以及如何更出色的完成了优化工作来介绍HTTP2.0
- 二进制分帧
- 首部压缩
- 流量控制
- 多路复用
- 请求优先级
- 服务器推送
二进制分帧
在不改变HTTP1.x的语义、方法、状态码。URL以及首部字段的情况下,HTTP2.0是怎样突破HTTP1.1的性能限制,改进传输性能,实现低延迟高吞吐量的呢?关键之一就是在应用层(HTTP)和传输层(TCP)之间增加一个二进制分帧层。
在整理二进制分帧及其作用的时候我们先来铺垫一点关于帧的知识:
- 帧:HTTP2.0通信的最小单位,所有帧都共享一个8字节的首部,其中包含帧的长度、类型、标志、还有一个保留位,并且至少有标识出当前帧所属的流的标识符,帧承载着特定类型的数据,如HTTP首部、负荷、等等。
- 消息:比帧大的通讯单位,是指逻辑上的HTTP消息,比如请求、响应等。由一个或多个帧组成
- 流:比消息大的通讯单位。是TCP连接中的一个虚拟通道,可以承载双向的消息。每个流都有一个唯一的整数标识符
什么是二进制分帧
在二进制分帧层上,HTTP2.0会将所有传输信息分割为更小的消息和帧,并对它们采用二进制格式的编码将其封装。其中,HTTP1.X中的首部信息header封装到Headers帧中,而request body将被封装到Data帧中。
二进制分帧如何工作
HTTP2.0通信都在一个TCP连接上完成,这个连接可以承载任意数量的双向数据流,相应的每个数据流以消息的形式发送。而消息由一或多个帧组成,这些帧可以乱序发送,然后根据每个帧首部的流标识符重新组装。
二进制分帧对性能优化工作的贡献
二进制分帧主要是为下文中的各种特性提供了基础。它能把一个数据划分封装为更小更便捷的数据。首先是在单链接多资源方式中,减少了服务端的链接压力,内存占用更少,链接吞吐量更大。这一点可以结合下文中的多路复用来体会。另一方面,由于TCP链接的减少而使网络拥塞状态得以改善,同时慢启动时间的减少。使拥塞和丢包恢复的速度更快。
首部压缩
HTTP1.1并不支持HTTP首部压缩,为此SPDY和HTTP2.0出现了。SPDY是用的是DEFLATE算法,而HTTP2.0则使用了专门为首部压缩设计的HPACK算法。
什么是首部压缩
HTTP1.x每次通讯(请求或响应)都会携带首部信息用于描述资源属性。而HTTP2.0在客户端和服务端之间使用首部表来跟踪和存储之前发送的键值对。请求与响应首部的定义在HTTP2.0中基本没有变,只是所有首部键必须全部小写,而且要求行要独立为:method:、:scheme:、:host:、:path:这些键值对
首部压缩如何工作
对于相同的数据,不再重新通过每次请求和响应发送。每个新的首部键值对要么追加到当前表的末尾,要么替换表中之前的值。首部表在HTTP2.0的链接存续期内始终存在,由客户端和服务端共同渐进的更新。
首部压缩性能优化工作的贡献
首部表在HTTP2.0使用了首部压缩的技术。使报头更紧凑,更快速传输,有利于移动网络环境。减少每次通讯的数据量,使网络拥塞状态得以改善。
流量控制
HTTP2.0为数据流和连接的流量提供了一个简单的机制:
- 流量基于HTTP链接的每一跳进行,而非端到端的控制
- 流量控制基于窗口更新帧进行,即接收方广播自己准备接收某个数据流的多少字节,以及对整个链接要接收多少个字节。
- 流量控制有方向性,即接收方可能根据自己的情况为没个流乃至整个链接设置任意窗口大小
- 流量控制可以由接收方禁用,包括针对个别的流和针对整个链接。
- 帧的类型决定了流量控制是否适用于帧,目前只有DATA帧服从流量控制,所有其他类型的帧并不会消耗流量控制窗口的空间。这保证了重要的控制帧不会被流量控制阻塞
多路复用
在HTTP1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量的限制。超过限制数目的请求会被阻塞。而HTTP2.0中的多路复用优化了这一性能。
什么是多路复用
基于二进制分帧层,HTTP2.0可以在共享TCP链接的基础上同时发送请求和响应。HTTP消息被分解为独立的帧,而不破坏消息本身的语义,交错发出去,在另一端根据流标识符和首部将他们重新组装起来。
多路复用如何工作
我们来通过与HTTP1.X的对比来看看他是如何工作的。
HTTP1.x
HTTP2.0
多路复用对性能优化工作的贡献
- 可以并行交错的发送请求和响应,这些请求和响应之间互不影响
- 只使用一个链接即可并行发送多个请求和响应
- 消除不必要的延迟,从而减少页面加载的时间
- 不必再为绕过HTTP1.x限制而多做很多工作
请求优先级
把HTTP消息分为很多独立帧之后,就可以通过优化这些帧的交错和传输顺序进一步优化性能。
什么是请求优先级
每个流都可以带有一个31bit的优先值:0表示最高优先级;2的31次方-1表示最低优先级。
请求优先级如何工作
客户端明确指定优先级,服务端可以根据这个优先级作为交互数据的依据,比如客户端优先设置为.css>.js>.jpg。服务端按此顺序返回结果更加有利于高效利用底层连接,提高用户体验。然而,在使用请求优先级时应注意服务端是否支持请求优先级,是否会引起队首阻塞问题,比如高优先级的慢响应请求会阻塞其他资源的交互。
请求优先级对性能优化工作的贡献
服务器可以根据流的优先级控制资源分配(CPU、内存、宽带),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。浏览器可以在发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序。这样请求就不用排队了,既节省了时间,又最大限度的利用了每个连接。
服务器推送
HTTP2.0新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确的请求。
什么是服务器推送(HTTP2.0中)
服务端根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。如下图,客户端请求stream 1(/page.html)。服务端在返回stream 1的消息的同时推送了stream 2(/script.js)和stream 4(/style.css)
服务器推送如何工作
- PUSH_PROMISE帧是服务端向客户端有意推送资源的信号。
- PUSH_PROMISE帧中只包含预推送资源的首部。如果客户端对PUSH_PROMISE帧没有意见,服务端在PUSH_PROMISE帧后发送响应的DATA帧。如果客户端已经缓存了该资源,不需要推送,可以拒绝PUSH_PROMISE帧。
- PUSH-PROMISE必须遵循请求-响应原则,只能借着对请求的响应推送资源。
- PUSH_PROMISE帧必须在返回响应之前发送,以免客户端出现竞态条件(竞态条件是指在多线程的情况下不同的执行顺序会导致计算机执行出不同的结果正确性不同)
- HTTP2.0连接后,客户端与服务端交换SETTINGS帧,借此限定双向并发的最大数量。因此,客户端可以限定推送流的数量,或者通过把这个只设置为0来完全禁止服务器推送。
- 所有推送的资源都必须遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方的确认才行。
服务器推送对性能优化工作的贡献
服务端推送是一种在客户端请求之前发送数据的机制。在HTTP2.0中,服务器可以对一个客户端的请求发送多个响应。如果一个请求是由你的主页发送的,服务器可能会响应主页内容、logo以及样式表,因为他知道客户端会用到这些东西。这样不但减轻了数据传送冗余步骤,也加快了页面响应的速度,提高了用户体验。