HTTP/2 新特性浅析

2018-05-06  本文已影响247人  secondplayer

HTTP发展简史

HTTP/0.9

GET /index.html

HTTP/1.0

GET / HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
HTTP/1.0 200 OK 
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

HTTP/1.1

HTTP/2

二进制协议

HTTP/2之前的协议都是基于ASCII码,好处是可读性好,容易上手。其缺点是可选的空格以及多变的终止符给识别帧造成了一些困难。采用二进制协议可以使得帧的识别更简单,并且传输信息更高效。其缺点是不便于调试,这就需要我们使用相应的工具来理解二进制的内容。

HTTP/2完全采用二进制协议,头信息和数据体都是二进制的,统称为(frame)。下图展示了同一个请求在HTTP/1.1和HTTP/2的对应关系,可见请求在HTTP/2中分为了两部分:头部帧和数据帧。

一个帧的基本格式如下:

所有帧都由一个9字节的header和可变长的payload组成,各字段定义如下:

多路复用

为了说明什么是多路复用,我们先需要明确下面几个概念:

这些概念的关系总结如下:

在HTTP/1.1中,如果客户端为了提高性能想要在一个TCP连接内同时发起多个请求,每个请求必须按顺序被服务器依次响应,如果某一个请求特别耗时,那么后面的请求将会被一直阻塞。

而在HTTP/2中,如果在一个TCP连接内同时发起多个请求,每个消息可以被拆成互不依赖的帧并且各帧之间交错发送,然后在另一端重新把帧组装起来。这个特性就叫做多路复用。

上图展示了同一个连接内并行的多个数据流。客户端正在向服务器传输一个数据帧(数据流5),与此同时,服务器正向客户端交错发送数据流1和数据流3的一系列帧。因此,一个连接上同时有三个并行数据流。

头部压缩

每个HTTP请求时都会承载一组表头。在HTTP/1.x中表头是以纯文本形式传输,通常需要500~800字节的开销,如果有cookie的话甚至会达到上千字节。为了减少这种开销并且提升性能,HTTP/2使用了HPACK算法进行压缩,具体来说包含了如下两种简单并强大的技术:

如上图所示,最左边是原始的请求头,第一行的:method GET通过查找静态索引表得到索引值为2,所以HPACK算法将其编码为2。最后第二行的user-agent Mozilla/5.0 ...不在静态索引表里,但在动态索引表里查到索引值为62,所以HPACK算法将其编码为62。最后一行的两个字段均未在索引表里查到,所以分别对其进行Huffman编码。

服务器推送

HTTP/2新增的另一个强大的功能是允许服务器除了可以响应客户端请求,还可以向客户端推送额外的资源。

通常当我们请求一个网页时,客户端解析HTML源码,发现有js或css等其他静态资源,然后再发起请求下载静态资源。而实际上,当客户端请求网页后,服务器完全可以预判客户端接下来要请求相关的静态资源,那为什么不让服务器提前推送这些资源,从而减少额外的延迟时间呢?HTTP/2为此提出了服务器推送机制,服务器端可以通过发起PUSH_PROMISE帧告知客户端,客户端收到服务器想要推送资源的意图后,可以决定是否接收推送。

事实上,如果你在网页中内联CSS或Javascript,那么你已经体验过服务器推送了。使用HTTP/2,我们不仅可以获得相同效果,还可以获得更多的性能优势:

服务器推送功能虽然很强大,但在实际使用中还需要考虑一些问题。第一个问题是如果客户端已经有缓存了,那么推送资源就是一种浪费。一种解决方法是只在用户第一次访问的时候推送资源。第二个问题是目前我们一般把静态资源放在CDN上,目前大部分CDN还不支持服务器推送,那么CDN和服务器推送到底哪个效果更好,这个可能还需要一些测试数据来做评判。

参考资料

上一篇下一篇

猜你喜欢

热点阅读