从HTTP的发展史,彻底掌握HTTP——第二篇,来自HTTP2.0的进化

312 阅读7分钟

前言

大家好,我是抹茶。接着上篇从HTTP的发展史,彻底掌握HTTP——第一篇,从诞生到HTTP1.0的演进我们继续研究HTTP/ 2.0。

上篇提到,TCP为了信息的可靠性考虑,如果传输过程中有丢包的情况,需要重传包,在这个过程中其他的传输需要等待前面的包完成重传后才可以继续工作,这就会出现队头堵塞问题。此外,HTTP/ 1.1对带宽的利用率不高。HTTP/1.1 依旧存在很多性能瓶颈。

HTTP/1.1的主要问题

HTTP/1.1的核心问题是对带宽的利用率不高

带宽是指每秒最大能发动或者接收的字节数。我们把每秒能发送的最大字节数称为上行带宽,每秒能够接收的最大字节数称为下行带宽

HTTP/ 1.1对带宽的利用率不高,是因为HTTP/1.1很难将带宽用满。比如100M带宽,实际下载速度能达到12.5M/S,而采用HTTP/1.1时,也许在加载页面资源时最大只能使用到2.5M/S,很难将2.5M全部拉满。

出现这个问题的主要原因有下面三点:

1. TCP的慢启动

一个TCP建立之后,就进入了发送数据状态,刚开始TCP协议会用一个非常慢的速度去发送数据,然后慢慢加快发送数据的速度,直到发送数据的速度达到一个理想状态,我们把这个过程称为慢启动

慢启动的设计目的是TCP为了减少网络拥塞,是不好去改变的。

慢启动是怎么带来性能问题的呢?

在页面初始化渲染时,需要用到HTML、CSS文件和JavaScript文件,TCP的慢启动就导致这些请求的耗时更长,增加了页面首次渲染的时长。

2. 多条TCP连接,会竞争固定的带宽

假设系统同时建立了多条TCP连接,当带宽充足时,每条连接发送或者接收的速度都会慢慢增加,一旦带宽不足的时候,这些TCP连接又会慢慢减少发送和接收的速度。比如一个页面有100个文件,使用了5个CDN,那么加载该页面的时候需要建立6*5(6是因为同一个域名最多建立6个TCP连接),也就是30个TCP连接来下载资源,在下载过程中,当发现带宽不足的时候,各个TCP连接就需要动态减慢接收数据的速度。

这样会导致关键资源的下载速度被影响。有的TCP连接下载的是首屏必须的HTML、CSS、JS文件资源,有的是图片、视频资源,TCP连接之间无法协商让哪些关键资源优先下载,所以关键资源的下载速度会受到影响。

3. HTTP/1.1的队头堵塞问题

上面也提到过。HTTP/1.1在进行持久连接的时候,一个TCP管道可以被多个请求使用,但是在一个管道中同一时刻只能处理一个请求,当前面的请求没有完成时,后面的请求只能排队等待。

这是一个很严重的问题,因为阻塞请求的因素有很多,并且都是一些不确定的因素,假如有的请求被阻塞了5秒,那么后续排队的请求都要延迟等待5秒,在这个等待的过程中,带宽、CPU都被白白浪费了。

队头堵塞问题使得浏览器无法快速的并行请求数据,不利于页面的加载性能。

HTTP / 2.0 的多路复用

HTTP/ 1.1的主要问题是队头堵塞,而队头堵塞又是因为TCP的重传机制导致的,我们无法换掉TCP,所以需要规避TCP的慢启动和TCP连接之间的竞争问题。

HTTP/ 2.0的解决思路是一个域名只使用一个TCP长连接和消除队头堵塞问题,这就是多路复用机制

2.0的多路复用.png

如上图所示,你可以看到每个请求都有一个对应的ID,且响应的返回顺序和请求的顺序是可以不一样的。

在HTTP/2.0中,服务器端接收到这些请求后,可以根据自己的喜好来决定优先返回内容。因为每份数据都有对应的ID,浏览器在收到数据包之后,可以根据相同的ID,将其拼接出完整的HTTP响应数据,这样还带来了一个好处,服务器可以优先处理关键资源的请求。

多路复用的实现

HTTP/2.0通过增加一个二进制分帧层来实现多路复用,如下图所示。

2.0的协议栈.png

HTTP/2.0的请求和接收过程如下

  • 浏览器准备好请求的数据,包括了请求行、请求头信息,如果是POST方法,那么还有请求体。
  • 数据经过二进制分帧层处理之后,会转变成一个个带请求ID编号的帧,通过协议栈转发给服务器。
  • 服务器会将相同ID的帧组装成完整的请求。
  • 服务器处理请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
  • 同样,二进制分帧层会将这些响应数据转化为一个个带有ID编号的帧,经过协议栈转发给浏览器。
  • 浏览器接收到响应帧后,会根据ID编号将帧的数据提交给对应的请求。

通过引入二进制分帧层,HTTP/2.0就实现了多路复用。

HTTP/2.0只是引入了新的中间层,并没有改动其他的架构设计,所以不需要为HTTP/2.0去重建生态,HTTP/2.0推广起来也就相对更加轻松了。

HTTP/2.0的其他特性

1.可以设置请求优先级

在发送请求的时候,可以标记请求的优先级,这样服务器在接收到请求后,会优先处理优先级高的请求。

2.服务器推送

HTTP/ 2.0还可以直接将数据提前推送到浏览器。用户在请求HTML之后,服务器知道HTML页面会引用几个重要的JavaScript文件和CSS文件,在接收到HTML请求后,附带将要使用的CSS文件和JavaScirpt文件一并发送给浏览器,这样当浏览器解析完HTML文件之后,就能直接拿到需要的CSS文件和JavaScript文件,提升页面的渲染速度。

3.头部压缩

HTTP/ 2.0对请求头和响应头进行了压缩。场景如,浏览器有100个左右的引用资源,将这100个请求头的数据压缩为原来的20%,那么传输效率就能得到大幅提升。

总结

HTTP/ 2.0通过增加二进制分帧层,为每个请求包加上一个ID,所以这些包可以无序的发送和响应,只需要将相同ID的包拼接到一块,就能读出完整数据。

基于上面的设计,HTTP/2.0可以设置请求的优先级,服务器可以优先响应优先级高的资源,如果知道资源A依赖了资源B、C还可以响应资源A请求时将B、C推送给浏览器。

请求头和响应头是大部分请求都会有的,HTTP/2.0通过压缩头部的设计,提升了传输的效率。

以上就是本篇的所有内容,下一篇会接着写HTTP/ 3.0。然后希望可以写一个设置请求优先级的demo(总是有完美的计划,执行起来却很慢)。