HTTP/2是HTTP协定自1999年HTTP 1.1的改进版RFC 2616公布后的首个更新,前身是SPDY协定(Google),于2015年2月17日被批准。

HTTP/2规范于2015年5月以RFC 7540正式发表,少数支流浏览器曾经在2015年底反对了该协定。目前国内外大多数网站也都曾经反对了HTTP/2,比方 Google/Stackoverflow/Reddit,国内的 淘宝/Segmentfault/掘金/CSDN/博客园/36Kr等等都曾经全面反对了HTTP/2协定

HTTP/2 相比HTTP/1 来说,次要是性能上的大幅晋升,而且齐全没有没有改变 HTTP/1协定中的利用语义。 Method、State Code、URI 和Header等外围概念齐全没有变动

上面具体介绍HTTP/2 中的一些要害降级点

二进制的分层(Binary Framing Layer)

Binary Framing Layer 的设计,算是HTTP/2性能晋升的外围了。HTTP/2中在应用层又设计了一套BinaryFrame Layer,它定义了HTTP音讯在传输过程中的封装形式。不过这个Frame Layer和TCP 的 Packet可不是一回事,这个Frame Layer只是逻辑上的分层,在HTTP和TCP层之间,相似于Http Chunk

如上图所示,HTTP/2中的报文,在传输前都会被先构建成一个个的帧(Frame),每次Socket发送的最小单位是一个帧,每个帧都以二进制格局进行编码

二进制格局编码(Binary format encode)

在HTTP/1中,数据都是以文本编码的模式进行传输的。那么什么叫文本编码,什么叫二进制编码呢?

举个例子,协定中有一个长度的首部值为 11 ,这个数字在文本编码中(用字符串来示意),它会占用2个Byte,对应的字节为[49, 49],那么在二进制编码下,11如果是Unsigned Int类型,那么它会占用4个Byte,对应的字节为[0, 0, 0, 11]

下面这个例子,看起来二进制编码下占用更大了;其实大多数状况下,二进制编码的占用会更低。如果换个大点的数字2147483647,在文本编码下须要占用10个Byte,可二进制编码下还是只须要占用4个Byte

文本编码(Byte Array)二进制编码(Byte Array)
11[49, 49][0, 0, 0, 11]
2147483647[50, 49, 52, 55, 52, 56, 51, 54, 52, 55][127, -1, -1, -1]

二进制格局这个叫法尽管比拟容易引起歧义,不过大家都这么叫,那就是对的

不过既然都用二进制编码了,那么还能叫超文本传输(HyperText Transfer )吗……

比方在HTTP/1中,有一个Chunk编码,和下面提到的Binary Framing Layer有些类似,都是在TCP之上加了一层逻辑层。Chunk编码中有一个Length字段,就是用文本编码的,但Binary Framing 中的长度和其余字段都是用二进制编码,所以这也是HTTP/2新增的逻辑层叫Binary Framing的起因吧

二进制格局尽管占用更小,但不像文本编码那种直观,易于调试,肉眼很难间接看出数据的内容

流/音讯/帧(Stream/Message/Frame)

  • Stream - 流,已建设的双向字节流,是一条逻辑的链路,对应一次HTTP交互的残缺申请响应
  • Message - 音讯,一次HTTP的申请音讯,或者响应音讯;一次申请-响应的交互报文,属于一个Stream
  • Frame - 帧,HTTP/2 传输的最小单位,每个帧蕴含帧首部,首部中会蕴含所属流的ID,一个Message会被分成多个Frame进行传输,所属不同Stream的Frame能够交织发送,对端收到交织的Frame后再依据Stream进行组装

在HTTP/2中,(同源的)所有的通信都会在一个繁多的 TCP 连贯上执行,该连贯能够传输任意数量的Stream

如上图所示:一条TCP连贯,能够承载多条Stream,一条Stream蕴含一次残缺的申请和响应音讯,申请和响应音讯又会被拆分为多个Binary Frame进行传输

多路复用

HTTP/2中的多路复用,和I/O多路复用(I/O Multiplexing)可不是一回事。I/O多路复用指的是同一个过程监听多个Sock事件,而HTTP/2中的多路复用是指在一条TCP连贯上同时进行多个申请和响应音讯的传输。
**
在HTTP/1中,如果想并行的发送多个申请,那么须要建设多条TCP连贯,每个连贯同时只能解决一个申请;而且当TCP连贯过多时,还会造成TCP的排队

HTTP/2中新的Binary Frame Layer的设计解决了这个弊病,客户端和 服务器能够把 多条并行的HTTP 音讯合成为互不依赖的Frame(如下图所示),而后交织发送,最初对端会把这些交织的Frame按Stream分组重新组合起来

上图中蕴含了一个连贯上多个传输中的Stream:Client正在向服务端发送Stream5的Data Frame,同时Server也在向Client交织发送Stream1和Stream3的Frame,在这条TCP连贯上有3个申请 /响应的数据进行交互  

多路复用是HTTP/2性能晋升的外围,这种计划的劣势次要在于以下几点:

  • 并行处理多个申请/响应,不会产生利用层面的阻塞
  • 应用单个TCP连贯,大幅缩小资源占用

这里可能会有一个疑难,换成单个TCP连贯真的会更快吗?

其实不相对,HTTP/1中浏览器个别会限度单个域名的连接数。比方Chrome会限度单个域名连接数下限为6个(历史数据,不保障精确,可能不同版本有所差别),如果在带宽足够,负载也不高时,同时下载的文件在6个以内时,单连贯和多连贯速度没什么区别。

不过如果同时下载的文件超过6个时,超出6个的那些下载就须要排队期待,这个时候就有区别了,HTTP/1中的连贯模型会导致排队,而HTTP/2不会

针对上述问题也有一些解决方案,比如说Domain Sharding,将动态资源别离部署至多个域名站点,这样就能够肯定水平上绕过浏览器的连贯限度;或者时拼接动态资源,将多个动态资源文件合并至一个,升高连接数的占用

而HTTP/2中,基本就不必思考连接数的限度,因为它对同源的下载只会应用一个TCP连贯,天然也就没什么连贯限度的概念了。

不过这里可能会思考一个问题,多个申请的数据在单个TCP连贯中传输时,会产生阻塞或者排队吗?

其实不会,TCP滑动窗口大小的下限是65535,足够跑满你的带宽。不过在网络环境极其差的时候,还是会有些影响的,毕竟收到ACK太慢或丢包,不过这种状况下单连贯和多连贯都一样有问题;但在网络状况良好时,单连贯省去了额定的建设连贯的开销,而且在TCP的Slow Start的机制下,连贯刚建设时滑动窗口的大小是比拟小的,传输报文的速率会有所升高;不过在HTTP/2下,因为只有一条连贯,且多个申请的报文能够交织发送不必期待,上述的毛病都能够防止了。

总结一下,HTTP/2的多路复用机制并不是在所有场景下都可能晋升性能,只是在浏览器同时加载过多文件时才会大幅晋升性能,并行的申请越多HTTP/2和HTTP/1的差别会越显著,如果只是下载单个文件,这个多路复用并不能带来什么晋升

这个网站,提供了一个HTTP/2和HTTP/1在同时加载多个资源时的速度差别:https://http2.akamai.com/demo,这个网页中同时下载400个小图片,能够看到HTTP2的加载速度远超HTTP/1

不过HTTP/2的优化可不止连贯复用,还有首部压缩,流量管制等

首部压缩(Header Compression)

在HTTP/1中,报文中的Header时通过文本模式编码的,就像上面这样:

每个header name都会跟一个冒号,而后时一个可选的空格,每个header以CRLF结尾,最初还会保留一个空行作为header局部的完结标识

这些header每次传输会减少500-800字节的开销,如果算上HTTP cookie的化,甚至会减少上千个字节开销。为了缩小此开销,HTTP/2应用HPACK压缩格局压缩申请和响应Header数据:

  1. 通过动态霍夫曼编码(Huffman code)对发送的Header进行编码,升高Header的大小
  2. 要求客户端和服务器都保护和更新以前看到的Header的索引列表,而后将该列表用作无效编码先前传输的值的参考

客户端和服务端都会建设一个Header索引表,外面蕴含曾经发送或接管的header,当再次发送header数据时会先从这个header索引表中查找,如果找到就用非凡值替换这个反复header,这样升高了反复值的占用,减小了报文大小

如上图所示,Request 1和Request 2的header只有一个:path不同,那么在发送Request 2时其余只有:path须要残缺编码发送,其余header替换成对应反复的索引即可

总结

HTTP/2性能晋升的要害,次要在于新的二进制分层配合多路复用设计,升高了连接数的占用,浏览器环境下晋升会比拟显著

晚期的域名域名分片(Domain Sharding),资源文件合并(Bundle resources )这种针对HTTP/1的优化策略,在HTTP/2下也齐全不须要了;如果降级到HTTP/2,前端的一些构建工具最好也将构建策略调整一下,单域名+多文件会更适宜HTTP/2。

不过对于一些纯服务端环境下,比方服务端调用三方零碎的HTTP接口,不会有什么连接数的限度,然而单连贯下还是能够升高建设连贯的开销

加上HTTP/2的Header压缩,升高了HTTP的报文大小,进一步的晋升了HTTP/2的性能

参考

  • https://hpbn.co/http2/