HTTP/2对网络传输的优化
HTTP/2对网络传输的优化
HTTP/1.1存在问题
HTTP/1.1持久连接允许客户端在同一个TCP连接上,同时发送多个请求,而无需等待前一个请求的响应,以此来充分利用等待响应过程中的时间。
但是HTTP是文本协议,请求和响应之间没有序号标识关联,无法将乱序的响应和请求关联起来,发送完一个请求,必须等到响应后才能发送下一个请求。
因此HTTP/1.1持久连接存在以下缺陷:
解析效率低:文本协议为了便于解析,协议中会加入一些特殊字符作为分隔符号,消息内容变得冗长,而且解析过程复杂,需要进行字符比较
停等协议:客户端需要等到响应后,才能发送下一个请求,等待时间客户端资源和网络利用率低
队头阻塞:如果其中一个请求非常耗时,或者因为某些原因没有及时响应,后面其他请求就会被阻塞
头信息重复传输:HTTP是无状态的协议,每次请求和带上所有头信息,头信息都是没有压缩的,尤其是UserAgent Cookie这类不会频繁变动的内容,但占用空间却很大,这样会造成网络带宽和流量的浪费
为了优化上述问题,有以下2个方案:
- 减少请求数量:常见做法是合并资源文件,将css、base64图片等资源内联
- 增加连接个数:一般浏览器,会把一个域名的并发连接数增加到6-8个
这些优化策略,虽然可以在一定程度上提高传输性能,但并没有完全解决问题。
因此HTTP/2应运而生
HTTP/2
HTTP/2采用二进制格式传输数据,支持多路复用和头部压缩等特性,是对HTTP/1.1协议一次比较彻底的改进和升级。
HTTP/2二进制分帧层
HTTP/2为了实现乱序请求和响应的关联,使通信双方能并发请求和响应。
在应用层与传输层之间,增加了二进制分帧层,将HTTP由文本协议转换成二进制协议。
HTTP/2二进制分帧层的帧和流是2个核心概念
帧是数据传输的最小单位
帧头一共有9字节,其中包含:
- Length
- Type
- Flags
- Stream ID
- Payloa
HTTP/2把请求和响应报文,分成头部帧和数据帧,由type字段标识
流是一个逻辑上的概念
一个资源请求就是一个流,一个流由多个帧组成,用同一个流ID标识,接收方可以通过流ID将帧关联起来,从而实现乱序请求和响应关联
HTTP/2连接多路复用
在二进制分帧层的基础上,一条TCP连接通信双方可以并发的请求和响应,实现多路复用。
发送端会把每个文件切割成多个数据帧并且编号,不同文件标记不同的流ID,三个文件可以同时发送。
接收端收到数据会根据不同的流ID,重新组装还原数据。
多路复用解决了HTTP应用层队头阻塞的问题,多个资源可以同时发送。
如图蓝色为请求,红色为响应,响应可以不是顺序的,这减少HTTP/1.1请求后等待响应的延迟。
HTTP/2 HPACK压缩算法
HTTP/2 HPACK压缩算法模块
HTTP/2使用HPACK算法压缩头信息,用于减少头信息的大小,减少发送包的数量,从而降低延迟。
一次HTTP请求未经过压缩Header大约是2400 bytes。
使用HTTP/2经过压缩后,首次请求大小会减少到1574 bytes,后续请求会进一步减少到112 bytes。
HPACK算法分为3个模块:
- 静态表
- 动态表
- Huffman编码
HTTP/2 HPACK压缩算法的主要思路
算法的主要压缩思路,是通过静态字典表和动态字典表,共享已知的HTTP头部字段,使用索引号来代替HTTP头部字段名和值,从而减少传输数据大小。
同时使用Huffman编码压缩字符串,进一步减少传输数据的体积。
HTTP/2 HPACK压缩算法静态表
静态表是预定义,包含61个常见HTTP头部字段和值,这些字段和值都是写死在协议中。
发送方可以通过发送静态表中对应的索引号,来替代完整的HTTP头部字段和值,从而实现压缩。
HTTP/2 HPACK压缩算法动态表
动态表是动态生成的,其中存储了请求或响应中出现HTTP头部字段和值。
发送方可以将动态表中的部分内容发送给接收方,并通过发送动态表中对应索引号,来代替完整HTTP头部字段和值,从而进一步减少传输数据大小。
HTTP/2 HPACK压缩算法Huffman编码
Huffman编码,是一种基于字符出现频率,无损压缩编码方法。
通过赋予高频字符较短的编码,来实现数据压缩,而不会丢失任何信息。
在HPACK中,使用Huffman编码对HTTP头部字段和值进行压缩,从而进一步减少传输数据的体积。
总结
HTTP/2的新机制,优化HTTP/1.1网络性能缺陷、降低延迟、提高吞吐量,使得网页资源加载速度更快