http2.0技术介绍
Posted 青榴实验室
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了http2.0技术介绍相关的知识,希望对你有一定的参考价值。
1. 技术背景
目前几乎所有互联网上的内容都采用了HTTP1.1作为通信协议。人们在该协议上投入了大量精力,所以基于它的基础架构也得以日臻完善。得益于此,在现有的HTTP协议之上构建新的方案会比从底层建立新的协议要容易得多。
然而任何事物的更新都是为了弥补或修复上个版本的某些问题,那么我们来看看HTTP1.1都有哪些缺点以至于我们要使用HTTP2.0。
1.1. HTTP1.1缺点
HTTP1.1有以下几个主要缺点:
规范过于庞大:HTTP刚诞生的时候只被当作是一个相对简单直观的协议,但时间证明了早期的设计并不尽人意。于1996年发布的描述HTTP1.0规范的RFC 1945只有60页,但仅仅3年之后,描述HTTP1.1规范的RFC2616就一下增长到了176页。后续IETF小组对该规范进行更新时,它更是被拆分成了总页数更多的六个文档。总而言之,HTTP 1.1包含了太多细节和可选的部分,这让它变得过于庞大。
队首阻塞:HTTP1.0一次只允许在一个TCP连接上发起一个请求,HTTP1.1使用流水线技术(HTTP pipelining)处理请求并发。HTTP pipelining把多个HTTP请求放到一个TCP连接中一一发送,在发送过程中不需要等待服务器对前一个请求的响应;但是,HTTP1.1规定,服务器端的响应的发送要根据请求被接收的顺序排队,也就是说,先接收到的请求的响应也要先发送。这样造成的问题是,如果最先收到的请求的处理时间长的话,响应生成也慢,就会阻塞已经生成了的响应的发送,也就是造成队首阻塞。
网络延迟:HTTP1.1对网络延迟非常敏感,部分原因是HTTP pipelining还存有很多问题,所以对大部分用户来说这项技术是被默认关闭的。一些需要低延迟的场景如视频会议、游戏和一些类似无法预生成待发送数据流的服务很难获得优质快速的网络体验。客户端在需要发起多次请求时,通常只能采用建立多连接来减少延迟。
TCP未充分利用:HTTP1.1很难榨干TCP协议所能提供的所有性能,HTTP客户端和浏览器必须要另辟蹊径的去找到新的解决方案来降低页面载入时间。
信息冗余与传输量大:请求报文与响应报文首部信息冗余量大;数据未压缩,导致数据的传输量大。
1.2. HTTP1.1优化方案
在HTTP2.0之前,出现了很多针对HTTP1.1的优化方案,这些方案都存在一定局限性。
Spriting(图片合并)
Spriting是一种将很多较小的图片合并成一张大图,再用javascript或者CSS将小图重新“切割”出来的技术。网站可以利用这一技巧来达到提速的目的——在HTTP1.1里,下载一张大图比下载100张小图快得多。
但是当某些页面只需要显示其中一两张小图时,这种缓存整张大图的方案就显得过于臃肿。同时,当缓存被清除的时候,Spriting会导致所有小图片被同时删除,而不能选择保留其中最常用的几个。
Inlining(内容内嵌)
Inlining是另外一种防止发送很多小图请求的技巧,它将图片的原始数据嵌入在CSS文件里面的URL里。而这种方案的优缺点跟Spriting很类似。
Concatenation(文件合并)
大型网站往往会包含大量的JavaScript文件。开发人员可以利用一些前端工具将这些文件合并为一个大的文件,从而让浏览器能只花费一个请求就将其下载完,而不是发无数请求去分别下载那些琐碎的JavaScript文件。但凡事往往有利有弊,如果某页面只需要其中一小部分代码,它也必须下载完整的那份;而文件中一个小小的改动也会造成大量数据的被重新下载。这种方案也给开发者造成了很大的不便。
Sharding(域名分片)
Sharding就是把服务分散在尽可能多的主机上。最初的HTTP1.1规范提到一个客户端最多只能对同一主机建立两个TCP连接。因此,为了不和规范冲突,一些聪明的网站使用了新的主机名,这样用户就能和网站建立更多的连接,从而降低载入时间。后来两个连接的限制被取消了,现在的客户端可以轻松地和每个主机建立更多连接。但由于连接的上限依然存在,所以网站还是会用这种技术来提升连接的数量。而随着资源个数的提升,网站会需要更多的连接来保证HTTP协议的效率,从而提升载入速度。在现今的网站上,使用50甚至100个连接来打开一个页面已经并不罕见,而且这个数字仍然在缓慢的增长中。
1.3. 升级HTTP
1.3.1. SPDY协议
2012年google提出了SPDY的方案,优化了HTTP1.X的请求延迟,解决了HTTP1.X的安全性,具体如下:
降低延迟。针对HTTP高延迟的问题,SPDY优雅的采取了多路复用(multiplexing)。多路复用通过多个请求stream共享一个tcp连接的方式,解决了首部阻塞的问题,降低了延迟同时提高了带宽的利用率。
请求优先级。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY允许给每个request设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的html内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
header压缩。HTTP1.x的header很多时候都是重复多余的,选择合适的压缩算法可以减小包的大小和数量。
基于HTTPS的加密协议传输。大大提高了传输数据的可靠性。
服务端推送。采用了SPDY的网页,例如我的网页有一个sytle.css的请求,在客户端收到sytle.css数据的同时,服务端会将sytle.js的文件推送给客户端,当客户端再次尝试获取sytle.js时就可以直接从缓存中获取到,不用再发请求了。
SPDY构成图
SPDY位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议(将HTTP1.x的内容封装成一种新的frame格式),同时可以使用已有的SSL功能。
1.3.2. HTTP2.0:SPDY的升级
SPDY是HTTP2.0的催化剂,但SPDY并非HTTP2.0。2012年初,W3C向社会征集HTTP2.0的建议,HTTP-WG经过内部讨论,决定将SPDY规范作为制定标准的基础。
HTTP2.0与SPDY主要区别:HTTP2.0支持明文HTTP传输,而SPDY强制使用HTTPS;HTTP2.0消息头的压缩算法采用HPACK,而非SPDY采用的DEFLATE。
2. HTTP2.0协议原理
2.1. 二进制分帧层
二进制分帧层,是HTTP 2.0性能增强的核心。HTTP1.x在应用层以纯文本的形式进行通信,而HTTP2.0将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。这样,客户端和服务端都需要引入新的二进制编码和解码的机制。如下图所示,HTTP2.0并没有改变HTTP 1.x的语义,只是在应用层使用二进制分帧方式传输。
2.2. 数据流、消息和帧
新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。为了说明这个过程,我们需要了解 HTTP/2 的三个概念:数据流,消息和帧。
2.2.1. 帧(frame)
HTTP 2.0通信的最小单位,包括帧首部、流标识符、优先值和帧净荷等。
其中,帧类型又可以分为:
DATA:用于传输HTTP消息体;
HEADERS:用于传输首部字段;
SETTINGS:用于约定客户端和服务端的配置数据。比如设置初识的双向流量控制窗口大小;
WINDOW_UPDATE:用于调整个别流或个别连接的流量
PRIORITY:用于指定或重新指定引用资源的优先级。
RST_STREAM:用于通知流的非正常终止。
PUSH_PROMISE:服务端推送许可。
PING:用于计算往返时间,执行“活性”检活。
GOAWAY:用于通知对端停止在当前连接中创建流。
标志位用于不同的帧类型定义特定的消息标志。比如DATA帧就可以使用End Stream: true表示该条消息通信完毕。流标识位表示帧所属的流ID。优先值用于HEADERS帧,表示请求优先级。R表示保留位。
2.2.2. 消息(message)
消息是指逻辑上的HTTP消息(请求/响应)。一系列数据帧组成了一个完整的消息。比如一系列DATA帧和一个HEADERS帧组成了请求消息。
2.2.3. 流(stream)
流是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。所有HTTP2.0通信都在一个TCP连接上完成, 这个连接可以承载任意数量的双向数据流Stream。相应地,每个数据流以消息的形式发送,而消息由一或多个帧组成,这些帧可以乱序发送, 然后根据每个帧首部的流标识符重新组装。
2.3. 多路复用
HTTP/2 中基于二进制分帧层,实现了完整的请求和响应复用:客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。正因为打破了相互依赖的关系,所以只要tcp没有人在用那么就可以发送已经生成的requst或者reponse的数据,在两端都不用等,从而彻底解决了http协议层面的队首阻塞问题。
上图展示了同一个连接内并行的多个数据流。客户端正在向服务器传输一个 DATA 帧(数据流5),与此同时,服务器正向客户端交错发送数据流1和数据流3的一系列帧。因此,一个连接上同时有三个并行数据流。
将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP/2 最重要的一项增强。事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升,因为我们可以:
并行交错地发送多个请求,请求之间互不影响。
并行交错地发送多个响应,响应之间互不干扰。
使用一个连接并行发送多个请求和响应。
不必再为绕过 HTTP1.x 限制而做很多工作。
消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间。
等等…
HTTP2.0成功解决了HTTP1.x的队首阻塞问题,同时也不需要通过pipeline机制多条TCP连接来实现并行请求与响应,减少了TCP连接数,对服务器性能也有很大的提升。
2.4. 请求优先级
把HTTP消息分解为很多独立的帧之后, 就可以通过优化这些帧的交错和传输顺序, 进一步提升性能。为了做到这一点,每个流都可以带有一个31比特的优先值:
0表示最高优先级,
-1表示最低优先级。
有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。具体来讲,服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽), 而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。
HTTP2. 0没有规定处理优先级的具体算法,只是提供了一种赋予数据优先级的机制, 而且要求客户端与服务器必须能够交换这些数据。这样一来,优先值作为提示信息,对应的次序排定策略可能因客户端或服务器的实现而不同:客户端应该明确指定优先值,服务器应该 根据该值处理和交付数据。
在实际应用中不能过分迷信请求优先级,需要注意以下问题:
服务端是否支持请求优先级,
会否引起队首阻塞问题,比如高优先级的慢响应请求会阻塞其他资源的交互。
2.5. 首部压缩
HTTP的每一次通信都会携带一组首部,用于描述传输的资源及其属性。在HTTP1. x中, 这些元数据都是以纯文本形式发送的,通常会给每个请求增加500~800字节的负荷。如果 算上HTTP cookie,增加的负荷通常会达到上千字节。为减少这些开销并提升性能,HTTP2.0会压缩首部元数据:
HTTP2.0在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
首部表在HTTP2.0的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值。
于是,HTTP2.0连接的两端都知道已经发送了哪些首部,这些首部的值是什么,从而可以针对之前的数据只编码发送差异数据。
HTTP2.0首部的差异化编码
上图中,第二个请求只需要发送变化了的路径首部(:path),其他首部没有变化,不用再发送了。这样 就可以避免传输冗余的首部,从而显著减少每个请求的开销。
另外,HTTP2.0使用了首部压缩技术,压缩算法使用HPACK,可让报头更紧凑,更快速传输,有利于移动网络环境。
2.6. 流控制
流控制是一种阻止发送方向接收方发送大量数据的机制,以免超出后者的需求或处理能力:发送方可能非常繁忙、处于较高的负载之下,也可能仅仅希望为特定数据流分配固定量的资源。
由于HTTP2.0数据流在一个TCP连接内复用,TCP流控制既不够精细,也无法提供必要的应用级API来调节各个数据流的传输。为了解决这一问题,HTTP 2.0为数据流和连接的流量控制提供了一个简单的机制:
流量控制基于每一跳进行,而非端到端的控制;
流量控制基于窗口更新帧进行,即接收方广播自己准备接收某个数据流的多少字节,以及对整个连接要接收多少字节;
流量控制窗口大小通过 WINDOW_UPDATE 帧更新,这个字段指定了流 ID 和窗口大小递增值;
流量控制有方向性,即接收方可能根据自己的情况为每个流乃至整个连接设置任意窗口大小;
流量控制可以由接收方禁用,包括针对个别的流和针对整个连接。
2.7. 服务器推送
HTTP 2.0增加了服务端推送功能,服务端可以根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。如下图所示,客户端请求stream 1,/page.html。服务端在返回stream 1消息的同时推送了stream 2(/script.js)和stream 4(/style.css)。
PUSH_PROMISE帧是服务端向客户端有意推送资源的信号。
如果客户端不需要服务端Push,可在SETTINGS帧中设定服务端流的值为0,禁用此功能
PUSH_PROMISE帧中只包含预推送资源的首部。如果客户端对PUSH_PROMISE帧没有意见,服务端在PUSH_PROMISE帧后发送响应的DATA帧开始推送资源。如果客户端已经缓存该资源,不需要再推送,可以选择拒绝PUSH_PROMISE帧。
PUSH_PROMISE必须遵循请求-响应原则,只能借着对请求的响应推送资源。
2.8. 协议协商机制
HTTP2.0的设计之初是不改动HTTP的语义、方法、状态码、URI及首部字段等核心概念,即不期望像用户暴露出HTTP2.0实现的复杂性。HTTP2.0依然与HTTP1.x保持一致,使用http和https来完成请求,前者对应于h2c(Http2 over cleartext TCP),后者则对应于h2(Http2 over TLS)。
所以,在发起Http请求时,对于HTTP2.0和HTTP1.x其实没有任何区别。对于同样的URI:https:\xxx或者http:\xxx,客户端在发起新请求之前,必须能发现服务器及所有设备是否支持HTTP/2协议,这就依赖于双端对于协议的协商机制了。
HTTP/2协议包含两种实现类型:h2c基于常规的非加密信道建立的HTTP/2的连接;h2基于TLS协议建立起来的HTTP/2的连接。针对h2c和h2,协商的方式是不同的。
2.8.1. H2协商
基于TLS的HTTP/2协商则依赖于ALPN协商机制。起初,Google在SPDY协议中开发了一个名为NPN(Next Protocol Negotiation,下一代协商)的TLS扩展,随着SPDY被HTTP/2所取代,NPN也被修订为ALPN(Application Layer Protocol Negotiation,应用层协议协商)。在TLS握手阶段,通信双方原本就要进行加密套件等的协商,ALPN作为起拓展加入握手协商过程中,对通信不会增添性能影响。
2.8.2. H2C协商
通过常规非加密信道建立HTTP2.0连接需要多做一点工作。因为HTTP1.0和HTTP2.0都使用同一个端口(80),没有服务器是否支持HTTP2.0的其他任何信息,此时客户端只能使用HTTP Upgrade机制通过协调确定适当的协议。
客户端必须通过Upgrade头部列出要升级到的协议和版本,并且还要包含一个HTTP2-Settings的头部,如下:
如果服务器不支持HTTP/2,便会忽略upgrade头部,直接回应Http1.x的Response:
如果服务器支持HTTP/2,则会以101的状态码回应,并且可以在响应正文,直接发送HTTP/2的帧:
3. HTTP2.0已知实现
目前已经支持HTTP/2的实现中默认都支持H2协商机制,部分实现对H2,H2C协商机制都支持,具体支持情况可参考链接:
https://github.com/http2/http2-spec/wiki/Implementations
Akamai公司建立了一个官方演示(链接:https://http2.akamai.com/demo)
用以说明HTTP2.0相比之前的HTTP1.1性能上的大幅度提升。同时请求379张图片,从Load time的对比可以看出HTTP2.0在速度上的优势:
4. HTTP2.0不足
单连接开销比较大。首部压缩使用HPACK数据压缩算法更新两端的查找表,这样可以让连接有状态,而破坏状态就意味着要重建查找表,另外单连接占用内存较多。
SSL性能影响。虽然HTTP2.0协议并没声明一定要用SSL,但是Chrome等主流浏览器强制要求使用HTTP2.0必须要用上SSL。
对下载大文件不利。如果你的应用主要提供大文件下载或者流媒体播放,那可能不想用TLS,而且在只有一个流的情况下,多路复用也体现不出什么优势。
需要抛弃针对HTTP1.x的优化。HTTP1.x优化在支持HTTP/2的浏览器中会影响性能,因此可能需要花时间把它们推倒重来。
5. 结束语
HTTP2.0正处于逐步应用到线上产品和服务的阶段,可以预见未来会有不少新的坑产生和与之对应的优化技巧,HTTP1.x和SPDY也将在一段时间内继续发挥余热。作为工程师,需要了解这些协议背后的技术细节,才能打造高性能的网络框架,从而提升我们的产品体验。
6. 参考文献
1.《Web性能权威指南》
2.《http2-explained》
3.https://blog.csdn.net/zhuyiquan/article/details/69257126
4.https://github.com/bagder/http2-explained/tree/master/zh
5.https://github.com/http2/http2-spec/wiki/Implementations
6.https://sq.163yun.com/blog/article/189871246785400832
7.https://http2.akamai.com/demo
8.https://www.cnblogs.com/sunsky303/p/9221220.html
青榴实验室---超高清视频技术的传播者
以上是关于http2.0技术介绍的主要内容,如果未能解决你的问题,请参考以下文章