1.1 协议目标
异步连接多路复用;
头部压缩;
请求/响应管线化;
保持与HTTP 1.1语义的向后兼容性也是该版本的一个关键目标。
HTTP/2是HTTP协议自1999年HTTP 1.1发布后的首个更新,主要基于SPDY协议。SPDY是一种HTTP兼容协议,由Google发起,Chrome、Opera、Firefox以及Amazon Silk等浏览器均已提供支持。HTTP实现的瓶颈之一是其并发要依赖于多重连接。HTTP管线化技术可以缓解这个问题,但也只能做到部分多路复用。此外,已经证实,由于存在中间干扰,浏览器无法采用管线化技术。SPDY在单个连接之上增加了一个帧层,用以多路复用多个并发流。帧层针对HTTP类的请求响应流进行了优化,因此运行在HTTP之上的应用,对应用开发者而言只要很小的修改甚至无需修改就可以运行在SPDY之上。SPDY对当前的HTTP协议有4个改进:
1) 多路复用请求;
2) 对请求划分优先级;
3) 压缩HTTP头;
4) 服务器推送流(即Server Push技术);
SPDY试图保留HTTP的现有语义,所以cookies、ETags等特性都是可用的。
HTTP/2与SPDY的比较:
HTTP/2的开发基于SPDY进行跃进式改进。在诸多修改中,最显著的改进在于,HTTP/2使用了一份经过定制的压缩算法,基于霍夫曼编码,以此替代了SPDY的动态流压缩算法,以避免对协议的Oracle攻击(攻击者通过握手将HTTPS通信协议降低到SSLv3.0之后,将会拦截到经过SSLv3.0加密过的数据,Padding Oracle攻击可以解密这些数据。)——这一类攻击以CRIME为代表。此外,HTTP/2禁用了诸多加密包,以保证基于TLS的连接的前向安全。
2015年9月,Google 宣布了计划,移除对SPDY的支持,拥抱 HTTP/2。
1.2 HTTP/2协议介绍
HTTP/2提供HTTP语义优化的运输。一个HTTP/2连接通过一个TCP连接(上面运行的应用程序级协议[TCP] )。 客户端是TCP连接发起者。
HTTP/2提供HTTP语义的有效序列化。 HTTP请求和响应编码为长度前缀的帧。HTTP标头字段被压缩成一系列包含头块碎片帧。
HTTP复用:HTTP/2提供了在单个连接上复用HTTP请求和响应的能力。 多个请求或响应可以同时在一个连接上使用流。为了保持独立的流,流控制和优先级是必要的。
HTTP语义:HTTP/2定义HTTP请求和响应如何映射到流,并引入了新的互动模式,服务器推送。
新的二进制格式(Binary Format),有别于HTTP/1.1在连接中的明文请求,HTTP/2与SPDY一样,将一个TCP连接分为若干个流(Stream),每个流中可以传输若干消息(Message),每个消息由若干最小的二进制帧(Frame)组成。这也是HTTP/1.1与HTTP/2最大的区别所在。 HTTP/2中,每个用户的操作行为被分配了一个流编号(stream ID),这意味着用户与服务端之间创建了一个TCP通道;协议将每个请求分区为二进制的控制帧与数据帧部分,以便解析。这个举措在SPDY中的实践表明,相比HTTP/1.1,新页面加载可以加快11.81% 到 47.7%。
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP/2使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送(server push),同SPDY一样,HTTP/2也具有server push功能。
网站为了使请求数减少,通常采用对页面上的图片、脚本进行极简化处理。但是,这一举措十分不方便,也不高效,依然需要诸多HTTP链接来加载页面和页面资源。 HTTP/2引入了服务器推送,即服务端向客户端发送比客户端请求更多的数据。这允许服务器直接提供浏览器渲染页面所需资源,而无须浏览器在收到、解析页面后再提起一轮请求,节约了加载时间。
chrome安装HTTP/2 and SPDY indicator插件可以查看访问网站是否启用H2:
若闪电图标显示蓝色,表明该网站可以通过HTTP/2的方式访问。
服务端推送:
服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确地请求。
HTTP 2.0 连接后,客户端与服务器交换SETTINGS 帧,借此可以限定双向并发的流的最大数量。
所有推送的资源都遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。
服务器必须遵循请求- 响应的循环,只能借着对请求的响应推送资源。
服务器推送到底是什么?
服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。
普通的客户端请求过程:
服务端推送的过程:
HTTP/2推送比较复杂,也比较底层,它完整的Fetch路径如下图:
HTTP/2推送的工作原理:
页面:嘿example.com,能把你的首页让我看一看吗?
服务器:没问题!哦,在我给你发送首页的同时,还需要发送一些样式表、图片、JavaScript,以及一些JSON。
页面:额,好的。
页面:我已经看到HTML了,但貌似还需要一个样式……哦,好像你已经发过来了,酷!
服务器响应请求时,可以顺便包含额外的资源。例如包含一系列请求报头,这样稍后浏览器就知道如何匹配不同报头。这些额外的资源位于缓存中,当浏览器请求的资源与缓存中的匹配时即可直接从缓存中获取。
这种方法可以改善性能,原因在于可以提前发送可能需要的资源,而不需要等待浏览器索取,因此可以提高页面加载速度。
传统的HTTP/1.1页面加载:
从上图可以看到,在 GET / 这个请求发出后,就会需要等待大概20毫秒的时间去解析网页内容,然后才会开始对下一个资源 widget.css的请求。
启动了服务器推送的HTTP/2网页加载:
从中可以看到,DOM和其他额外的资源都不需要进行解析,客户端就已经可以下载 screen.css 这个资源了。这就不需要“浪费时间”在处理DOM和哪些额外的资源上面了,需要做的仅仅是发送另外一个请求到服务器端去把它们拿下来而已。
推送场景:
在合适的时机,推送合适的资源,Push比No Push带来的网站时延提升是明显的。在网络带宽足够承载推送资源的前提下,我们预先推送浏览器后续请求需要的资源,网站的整体加载时间得到缩短。但是现实网络环境有不一样的延时和带宽。慢速网络环境影响TCP拥塞窗口增长的速度,除非主页面请求足够小,Push才能看到效果。
即使是错误地实施某些推送策略(比如说推送过大文件),带来的最严重后果,也就是改善不明显。所以建议是多做一些推送策略的尝试,直到把合适的资源在合适的时机把资源推送给浏览器。
网站往HTTP/2的环境迁移是个趋势。迁往HTTP/2需要将页面的所有请求尽量收归到同一域名,并且剥离出主页面的资源文件成多个独立的请求。假如你的网站已迁移到HTTP/2,而且网站的主请求不大,但是可能会触发很多资源请求。建议push这些资源。另外不要推送存放在浏览器cookie的资源,这只会浪费带宽。
目前的Server Push推送机制没有解决浏览器已经具有资源缓存,而服务器已经推送到网络中,虽然浏览器可以发送RST桢拒绝推送流,但是服务器推送的资源已经在网络中等待浏览器接收。现在已经有一些规范草案案尝试用协商缓存摘要来解决问题。
CDN中的负载均衡机制可能会将低优先级的推送资源送入到系统缓存区,这会影响高优先级资源的推送效率问题。引入QUIC替代TCP,可以对缓存中推送资源进行分级,高优先级资源先发。
未来或将引入AI分析取代固定推送实现智能化推送。
关于HTTP2和HTTP1.x的区别大致可以看下图:
领取专属 10元无门槛券
私享最新 技术干货