天天看点

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

虽然http/2标准在2015年5月就以rfc 7540正式发表了,并且多数浏览器在2015年底就支持了。

但是,真正被广泛使用起来要到2018年左右,但是也是在2018年,11月ietf给出了官方批准,认可http-over-quic成为http/3。

2018年的时候,那时候http/2还是个新技术,刚刚开始有软件支持,短短两年过去了,现在http/3已经悄然而至了。

根据w3techs的数据,截至2019年6月,全球也仅有36.5%的网站支持了http/2。所以,可能很多网站还没开始支持http/2,http/3就已经来了。

所以,对于很多网站来说,或许直接升级http/3是一个更加正确的选择。

我默认大家对http/2有了一定的基本了解。

我们知道,http/2的诞生,主要是为了解决http/1.1中的效率问题,http/2中最核心的技术就是多路复用技术,即允许同时通过单一的http/2.0连接发起多重的请求-响应消息。

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

同时还实现了二进制分帧、header压缩、服务端推送等技术。

从http/1.0诞生,一直到http/2,在这24年里,http协议已经做过了三次升级,但是有一个关键的技术点是不变的,那就是这所有的http协议,都是基于tcp协议实现的。

流水的http,铁打的tcp。这是因为相对于udp协议,tcp协议更加可靠。

虽然在http/1.1的基础上推出http/2大大的提升了效率,但是还是有很多人认为这只是个"临时方案",这也是为什么刚刚推出没多久,业内就开始大力投入http/3的研发与推广了。

而这背后的深层次原因也正是因为他还是基于tcp协议实现的。tcp协议虽然更加可靠,但是还是存在着一定的问题,接下来具体分析下。

队头阻塞翻译自英文head-of-line blocking,这个词并不新鲜,因为早在http/1.1时代,就一直存在着队头阻塞的问题。

但是很多人在一些资料中会看到有论点说http/2解决了队头阻塞的问题。但是这句话只对了一半。

只能说http/2解决了http的队头阻塞问题,但是并没有解决tcp队头阻塞问题!

如果大家对于http的历史有一定的了解的话,就会知道。http/1.1相比较于http/1.0来说,最主要的改进就是引入了持久连接(keep-alive)。

所谓的持久连接就是:在一个tcp连接上可以传送多个http请求和响应,减少了建立和关闭连接的消耗和延迟。

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

引入了持久连接之后,在性能方面,http协议有了明显的提升。

另外,http/1.1允许在持久连接上使用请求管道,是相对于持久连接的又一性能优化。

所谓请求管道,就是在http响应到达之前,可以将多条请求放入队列,当第一条http请求通过网络流向服务器时,第二条和第三条请求也可以开始发送了。在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

但是,对于管道连接还是有一定的限制和要求的,其中一个比较关键的就是服务端必须按照与请求相同的顺序回送http响应。

这也就意味着,如果一个响应返回发生了延迟,那么其后续的响应都会被延迟,直到队头的响应送达。这就是所谓的http队头阻塞。

但是http队头阻塞的问题在http/2中得到了有效的解决。http/2废弃了管道化的方式,而是创新性的引入了帧、消息和数据流等概念。客户端和服务器可以把 http 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

因为没有顺序了,所以就不需要阻塞了,就有效的解决了http对队头阻塞的问题。

但是,http/2仍然会存在tcp队头阻塞的问题,那是因为http/2其实还是依赖tcp协议实现的。

tcp传输过程中会把数据拆分为一个个按照顺序排列的数据包,这些数据包通过网络传输到了接收端,接收端再按照顺序将这些数据包组合成原始数据,这样就完成了数据传输。

但是如果其中的某一个数据包没有按照顺序到达,接收端会一直保持连接等待数据包返回,这时候就会阻塞后续请求。这就发生了tcp队头阻塞。

http/1.1的管道化持久连接也是使得同一个tcp链接可以被多个http使用,但是http/1.1中规定一个域名可以有6个tcp连接。而http/2中,同一个域名只是用一个tcp连接。

所以,在http/2中,tcp队头阻塞造成的影响会更大,因为http/2的多路复用技术使得多个请求其实是基于同一个tcp连接的,那如果某一个请求造成了tcp队头阻塞,那么多个请求都会受到影响。

一提到tcp协议,大家最先想到的一定是他的三次握手与四次关闭的特性。

因为tcp是一种可靠通信协议,而这种可靠就是靠三次握手实现的,通过三次握手,tcp在传输过程中可以保证接收方收到的数据是完整,有序,无差错的。

但是,问题是三次握手是需要消耗时间的,这里插播一个关于网络延迟的概念。

网络延迟又称为 rtt(round trip time)。他是指一个请求从客户端浏览器发送一个请求数据包到服务器,再从服务器得到响应数据包的这段时间。rtt 是反映网络性能的一个重要指标。

HTTP-2做错了什么?刚刚辉煌2年就要被弃用了!?

我们知道,tcp三次握手的过程客户端和服务器之间需要交互三次,那么也就是说需要消耗1.5 rtt。

另外,如果使用的是安全的https协议,就还需要使用tls协议进行安全数据传输,这个过程又要消耗一个rtt(tls不同版本的握手机制不同,这里按照最小的消耗来算)

那么也就是说,一个纯http/2的连接,需要消耗1.5个rtt,如果是一个https连接,就需要消耗3-4个rtt。

而具体消耗的时长根据服务器和客户端之间的距离则不尽相同,如果比较近的话,消耗在100ms以内,对于用来说可能没什么感知,但是如果一个rtt的耗时达到300-400

ms,那么,一次连接建立过程总耗时可能要达到一秒钟左右,这时候,用户就会明显的感知到网页加载很慢。

基于上面我们提到的这些问题,很多人提出来说:既然tcp存在这些问题,并且我们也知道这些问题的存在,甚至解决方案也不难想到,为什么不能对协议本身做一次升级,解决这些问题呢?