写点什么

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

发布于: 4 小时前
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.1Host: 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/

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

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

发布于: 4 小时前阅读数: 2
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
HTTP协议之:HTTP/1.1和HTTP/2