HTTP-2 做错了什么?刚刚辉煌 2 年就要被弃用了!,mybatis 底层工作原理
同时还实现了二进制分帧、header 压缩、服务端推送等技术。
从 HTTP/1.0 诞生,一直到 HTTP/2,在这 24 年里,HTTP 协议已经做过了三次升级,但是有一个关键的技术点是不变的,那就是这所有的 HTTP 协议,都是基于 TCP 协议实现的。
流水的 HTTP,铁打的 TCP。这是因为相对于 UDP 协议,TCP 协议更加可靠。
虽然在 HTTP/1.1 的基础上推出 HTTP/2 大大的提升了效率,但是还是有很多人认为这只是个"临时方案",这也是为什么刚刚推出没多久,业内就开始大力投入 HTTP/3 的研发与推广了。
而这背后的深层次原因也正是因为他还是基于 TCP 协议实现的。TCP 协议虽然更加可靠,但是还是存在着一定的问题,接下来具体分析下。
HTTP/2 问题
队头阻塞
队头阻塞翻译自英文 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 协议有了明显的提升。
另外,HTTP/1.1 允许在持久连接上使用请求管道,是相对于持久连接的又一性能优化。
所谓请求管道,就是在 HTTP 响应到达之前,可以将多条请求放入队列,当第一条 HTTP 请求通过网络流向服务器时,第二条和第三条请求也可以开始发送了。在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。
但是,对于管道连接还是有一定的限制和要求的,其中一个比较关键的就是服务端必须按照与请求相同的顺序回送 HTTP 响应。
这也就意味着,如果一个响应返回发生了延迟,那么其后续的响应都会被延迟,直到队头的响应送达。这就是所谓的 HTTP 队头阻塞。
但是 HTTP 队头阻塞的问题在 HTTP/2 中得到了有效的解决。HTTP/2 废弃了管道化的方式,而是创新性的引入了帧、消息和数据流等概念。客户端和服务器可以把 HTTP 消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。
因为没有顺序了,所以就不需要阻塞了,就有效的解决了 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 是一种可靠通信协议,而这种可靠就是靠三次握手实现的,通过三次握手,TCP 在传输过程中可以保证接收方收到的数据是完整,有序,无差错的。
但是,问题是三次握手是需要消耗时间的,这里插播一个关于网络延迟的概念。
网络延迟又称为 RTT(Round Trip Time)。他是指一个请求从客户端浏览器发送一个请求数据包到服务器,再从服务器得到响应数据包的这段时间。RTT 是反映网络性能的一个重要指标。
我们知道,TCP 三次握手的过程客户端和服务器之间需要交互三次,那么也就是说需要消耗 1.5 RTT。
另外,如果使用的是安全的 HTTPS 协议,就还需要使用 TLS 协议进行安全数据传输,这个过程又要消耗一个 RTT(TLS 不同版本的握手机制不同,这里按照最小的消耗来算)
那么也就是说,一个纯 HTTP/2 的连接,需要消耗 1.5 个 RTT,如果是一个 HTTPS 连接,就需要消耗 3-4 个 RTT。
而具体消耗的时长根据服务器和客户端之间的距离则不尽相同,如果比较近的话,消耗在 100ms 以内,对于用来说可能没什么感知,但是如果一个 RTT 的耗时达到 300-400ms,那么,一次连接建立过程总耗时可能要达到一秒钟左右,这时候,用户就会明显的感知到网页加载很慢。
升级 TCP 是否可行?
基于上面我们提到的这些问题,很多人提出来说:既然 TCP 存在这些问题,并且我们也知道这些问题的存在,甚至解决方案也不难想到,为什么不能对协议本身做一次升级,解决这些问题呢?
其实,这就涉及到一个"协议僵化"的问题。
这样讲,我们在互联网上浏览数据的时候,数据的传输过程其实是极其复杂的。
我们知道的,想要在家里使用网络有几个前提,首先我们要通过运行商开通网络,并且需要使用路由器,而路由器就是网络传输过程中的一个中间设备。
中间设备是指插入在数据终端和信号转换设备之间,完成调制前或解调后某些附加功能的辅助设备。例如集线器、交换机和无线接入点、路由器、安全解调器、通信服务
器等都是中间设备。
在我们看不到的地方,这种中间设备还有很多很多,一个网络需要经过无数个中间设备的转发才能到达终端用户。
如果 TCP 协议需要升级,那么意味着需要这些中间设备都能支持新的特性,我们知道路由器我们可以重新换一个,但是其他的那些中间设备呢?尤其是那些比较大型的设备呢?更换起来的成本是巨大的。
而且,除了中间设备之外,操作系统也是一个重要的因素,因为 TCP 协议需要通过操作系统内核来实现,而操作系统的更新也是非常滞后的。
所以,这种问题就被称之为"中间设备僵化",也是导致"协议僵化"的重要原因。这也是限制着 TCP 协议更新的一个重要原因。
评论