CS揭秘 · 2021-08-23 0

HTTP协议之:HTTP/1.1和HTTP/2

简介

HTTP的全称是Hypertext Transfer Protocol,是在1989年World Wide Web发展起来之后出现的标准协议,用来在WWW上传输数据。HTTP/1.1是1997年在原始的HTTP协议基础上进行的补充和优化。

到了2015年,为了适应快速发送的web应用和现代浏览器的需求,发展出了新的HTTP/2协议,主要在手机浏览器、延时处理、图像处理和视频处理方面进行了优化。

基本上所有的现代浏览器都支持HTTP/2协议了,但是还有很多应用程序使用的是老的HTTP/1.1协议,本文将会介绍HTTP/1.1和HTTP/2的不同之处。

HTTP/1.1

HTTP 1.0 是由Timothy Berners-Lee在1989年作为World Wide Web的标准协议发布的。通常使用HTTP方法如:GET或者POST,以TEXT文本的形式在客户端和服务器端进行消息传输。

我们可以使用post man很方便的进行HTTP请求,如下所示:

GET /index.html HTTP/1.1
Host: www.flydean.com

客户端通过GET请求,请求服务器端的/index.html页面,使用的协议是HTTP/1.1,服务器端收到该请求之后,会将相应以文本的形式返回给客户端。

HTTP协议是对底层的TCP/IP协议的封装,因为我们不需要交接具体的报文拆分和封装的底层细节,只需要关注于具体的业务逻辑即可,非常的方便。

HTTP/2

HTTP/2是从SPDY协议发展出来的,它的发起者是Google,最初是为了在web交互中引入压缩、多路复用等新的技术,最终在2015年被作为HTTP/2协议的一部分。

之前我们讲到HTTP/1.1是以文本的形式进行传输的,这样的缺点就是数据占用的空间比较大,相较于HTTP/1.1来说HTTP/2使用的是二进制进行传输的,使用二进制对消息进行封装,同时保留了HTTP的语义,比如方法,头等。

这种二进制的封装对应用层是无感知的,对于应用来说,还是按照常用的方法来创建HTTP请求,将其封装成二进制的工作是由HTTP/2来完成的。

传输模式对比

在HTTP1.0中,每当客户端向服务器端请求页面的时候,往往返回的不是一个完整的页面,而是这个页面还需要的额外的资源链接信息,因为完整的页面需要所有的资源都下载完毕之后才能展示,所以在HTTP1.0中,客户端需要中断当前的连接,然后重新建立新的连接去请求资源。这会额外耗费多余的资源和时间。

在HTTP1.1中,引入了持久连接和管道的概念,这样不用每次请求都去重新开启和新建连接,HTTP默认底层的TCP连接是open的,除非手动告诉它要去关闭。在这种情况下,客户端可以使用同一个连接去和server进行交互,从而极大的提升HTTP的效率。

虽然在HTTP1.1中可以使用同一个连接进行数据传输了,但是对于这个连接来说,其中的请求是一一响应的,他们是有顺序的。如果最前面的请求被阻塞了,后面的请求也得不到响应。这种情况被称为head-of-line (HOL) blocking。

为了解决这个问题,可以在client和server端建立多个连接,这样就可以利用多个connection并行进行数据的传输,从而提升传输效率。

但是这样的缺点就是新建连接会消耗太多的资源,并且客户端和服务器端的连接个数也是有限的。

所以HTTP/2出现了。

在 HTTP/2 中,数据以二进制的的格式进行传输,其本身是将原始请求的切分成为更小的信息包,从而大大增加了数据传输的灵活性。

HTTP1.1需要建立多个TCP连接从而解决并行传输的问题,但是在HTTP/2 中只需要建立一个连接就够了。在这个连接中可以传输多个数据流,每个数据流中又包含多个message包,每个message又被切分为多个数据frame。

这些数据frame可以在传输期间交换位置,然后在接收的另一端重新组装。 交错的请求和响应可以并行运行,从而不会阻塞它们背后的消息,这个过程被称为多路复用。 多路复用的机制使得一个消息不用等待另外一个消息发送完成,从而解决了HTTP/1.1 中的队头阻塞问题。 这也意味着服务器和客户端可以发送并发请求和响应,从而实现更好的控制和更有效的连接管理。

多路复用虽然构建了多个消息流,但是只占用了一个TCP连接,从而减少整个网络的内存和处理占用空间,得到更好的网络和带宽利用率,从而降低整体运营成本。

单个TCP连接还提高了HTTPS协议的性能,因为客户端和服务器可以为多个请求/响应重用相同的安全会话。 在HTTPS中,在TLS或SSL握手期间,双方在整个会话期间使用单个密钥。 如果连接中断从新开始新的会话,则需要新生成的密钥进行进一步通信。 因此,维护单个连接可以大大减少HTTPS所需的资源。

请注意,尽管HTTP/2规范并未强制要求使用TLS,但许多主要浏览器仅支持带有HTTPS的HTTP/2。

流优先级

虽然HTTP/2解决了多个数据frame通常传输的问题,但是对于同一个资源来说,必须要等到的所有的数据frame都接受完毕之后才能展示,如果我们想优先展示某个资源该怎么做呢?

HTTP/2提供了流优先级的解决方案。

在客户端向服务器端发送消息的时候,消息会以流的形式在连接中传输,这些流可以分配1到256之间的权重来确定其请求的响应的优先级。 数字越大表示优先级越高。 除此之外,客户端还通过指定它所依赖的流的ID来说明每个流对另一个流的依赖关系。 如果省略父标识符,则认为该流依赖于根流。

服务器会使用流中的ID构建一个依赖树,从而确定其相应的顺序。

应用程序的开发人员可以根据需要自行设置请求的优先级,比如在网页中提供低分辨率的缩略图的同时提供低优先级的高分辨率的图像。通过为资源分配不同的优先级,开发人员能够更好地控制网页渲染。

缓冲区溢出处理

不管是哪种协议,客户端和服务器端在接收数据的时候都有一个缓冲区来临时存储暂时处理不了的数据,但是缓冲区的大小是有限制的,所以有可能会出现缓冲区溢出的情况,比如客户端向服务器端上传一个大的图片,就有可能导致服务器端的缓冲区溢出,从而导致一些额外的数据包丢失。

为了避免缓冲区溢出,各个HTTP协议都提供了一定的解决办法。

在HTTP1.1中,流量的控制依赖的是底层TCP协议,在客户端和服务器端建立连接的时候,会使用系统默认的设置来建立缓冲区。在数据进行通信的时候,会告诉对方它的接收窗口的大小,这个接收窗口就是缓冲区中剩余的可用空间。如果接收窗口大小为零,则说明接收方缓冲区已满,则发送方将不再发送数据,直到客户端清除其内部缓冲区,然后请求恢复数据传输。

因为HTTP1.1使用多个TCP连接,多以可以对每一个TCP连接进行单独的流量控制。但是HTTP2使用的是多路复用的模式,所以它的流量控制方式和HTTP1.1是不同的。

HTTP2是通过客户端和服务器端的应用中进行缓冲区大小消息的传输,是通过在应用层层面控制数据流,所以各个应用端可以自行控制流量的大小,从而实现更高的连接效率。

HTTP/2提供了更详细的控制级别,从而开启了更大优化的可能性。

预测资源请求

在一个典型的web应用中,当客户端发动一个GET请求到服务器端的时候,通常客户端会发现所以需要的不止一个资源,还可能包含了CSS或者其他JS等资源。但是客户端只有在首次获取到服务器端的响应时候才能真正确认到底需要哪些资源。然后需要额外请求这些资源以完成整个请求。但是这些额外的请求最终会增加连接加载时间。

那么有没有可能服务器在客户端请求之前将资源发送给客户端呢?我们看下HTTP1.1和HTTP2是怎么做的。

在HTTP1.1中,主要使用的资源内联的方式,比如将客户端所需要的CSS或者JS资源包含在服务器最初发送的HTML文档中,也就是做内联操作,从而减少客户端必须发送的请求总数。

但是这样的解决方案也有问题。因为一般来说资源内联一般是针对较小的资源来说的,如果资源文件太大的话,就会大大的增加HTML文件的大小,从而抵消减少连接提升的速度优势。

另外如果资源被放在HTML中,那么客户端就没有可能对这些资源进行缓存,从而影响整体的效率。

在HTTP/2中使用的是服务器推送。因为HTTP/2在同一个连接中可以发送多个stream,所以服务器可以将资源与请求的HTML页面一起发送到客户端,在客户端请求之前提供资源。 这个过程被称为服务器推送。

这样就可以在不用新开连接的同时,实现HTML文档和资源的分离和同时推送。

但是在HTTP/2中,服务器推送是由应用程序来控制的,所以控制起来会比较复杂。我们会在后续的文章中详细讲解HTTP/2的服务器推送。

压缩

通常为了减少数据在网络中的传输,我们需要对数据进行压缩,接下来我们看一下在HTTP1.1和HTTP2中都是怎么做的。

在HTTP1.1中,通常使用gzip对HTTP中的消息进行压缩,主要是针对CSS文件和javascript文件,但是HTTP的消息头还是由纯文本来发送的,另外由于cookie的使用,导致HTTP消息头的大小会越来越大,从而对程序的性能造成一定的影响。

在HTTP/2中,使用的算法是HPACK算法,同时可以对HTTP头和数据分别进行压缩,从而大大减少其大小。

总结

HTTP/2在HTTP1.1的基础上进行了更加细粒度的优化控制,并提供了包括多路复用、流优先级、流量控制、服务器推送和压缩等高级特性。非常强大。希望大家能够喜欢。

本文已收录于 http://www.flydean.com/02-http1-1-vs-http2/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!