HTTP 1.x 与 HTTP 2.0 的区别

HTTP 2.0 相比 HTTP 1.x 大幅提高了web性能,减少了网络延迟。接来下详细探索下 HTTP 2.0 是如何提高性能的。

先来看个 http/1.1 与 http/2 同时请求 379 张图片,所花费时间的对比。https://http2.akamai.com/demo

打开 Chrome Developer Tools 查看 Network 可以看到区别:
HTTP/1:

HTTP/2

HTTP/2的优势

1. 多路复用(Multiplexing)

在 HTTP 1.1 时代,为了能加快网页加载,一般会这么做:
1.将静态资源放在不同的域名下面
2.使用雪碧图技术将多张小图片合成一张大图
3.合并JS、CSS

因为一个TCP连接只能同时请求一个资源,所以为了同时请求多个资源,就要建立多个TCP连接(服务器也要更多的线程来处理请求)。

但是浏览器又会限制同一个域的同时请求数,Chrome是限制6个,总连接数是17个。

所以,又将资源放在多个域名下面(又会增加dns解析时间)

其他浏览器连接数限制如图:

虽然有些优化办法,但总有种拆东墙补西墙的感觉。但是有了HTTP 2.0,这些问题就迎刃而解了。
通过上面HTTP 2.0 加载资源的图可以看到,这些资源是同时加载的,后面加载的资源不需要排队等待,理论上,加载速度完全由带宽决定的,带宽有多大,就能传多快。

HTTP 2.0 传输模型如下:
image
因此 HTTP/2 可以很容易的去实现多流并行而不用依赖建立多个 TCP 连接,HTTP/2 把 HTTP 协议通信的基本单位缩小为一个一个的帧,这些帧对应着逻辑流中的消息。并行地在同一个 TCP 连接上双向交换消息。

2. 二进制分帧

在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段….. 的情况下,HTTP/2 是如何做到「突破 HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量」的 ?

关键之一就是在 应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。

在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。

HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流。

在过去, HTTP 性能优化的关键并不在于 高带宽,而是 低延迟。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。

HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

总结:

  • 单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大

  • 由于 TCP 连接的减少而使网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快

3. 首部压缩(Header Compression)

HTTP/1.1并不支持 HTTP 首部压缩,为此 SPDY 和 HTTP/2 应运而生, SPDY 使用的是通用的 DEFLATE 算法,而 HTTP/2 则使用了专门为首部压缩而设计的 HPACK 算法。

客户端发了两次请求,第一次请求有完整的http报文头部,第二次请求的时候只有一个path的字段不一样,但是这次报文头它只需要发送一个path的字段就好了,这样就大大减少了发送的量。这个的实现要求客户端和服务同时维护一个报文头表。

4. 服务端推送(Server Push)

在 HTTP 1.x,资源一般都是要等 html 解析到相应的文档标签(img、css、javascript),才会去下载对应的资源。但 HTTP 2 可以让服务器主动把资源推送客户端,不用等用到了才发请求。那么,试想一下,假如请求的页面是主页,那么服务端主动把logo、样式表推送过来,而不是等到解析到对应的元素才服务端请求(但事实上这点解析文档的时间我觉得可以忽略不计)。

这里也有一个同学亲身折腾的体验,Node HTTP/2 Server Push 从了解到放弃

官方说法:

为什么在浏览器中需要一种此类机制呢?一个典型的网络应用包含多种资源,客户端需要检查服务器提供的文档才能逐个找到它们。 那为什么不让服务器提前推送这些资源,从而减少额外的延迟时间呢? 服务器已经知道客户端下一步要请求什么资源,这时候服务器推送即可派上用场。

事实上,如果您在网页中内联过 CSS、JavaScript,或者通过数据 URI 内联过其他资产(请参阅资源内联),那么您就已经亲身体验过服务器推送了。 对于将资源手动内联到文档中的过程,我们实际上是在将资源推送给客户端,而不是等待客户端请求。 使用 HTTP/2,我们不仅可以实现相同结果,还会获得其他性能优势。 推送资源可以进行以下处理:

  • 由客户端缓存
  • 在不同页面之间重用
  • 与其他资源一起复用
  • 由服务器设定优先级
  • 被客户端拒绝

参考:
https://developers.google.com/web/fundamentals/performance/http2
https://www.zhihu.com/question/34074946/answer/75364178
https://zhuanlan.zhihu.com/p/29609078