阅读 76
大前端百科全书网络专题之http2/http3

大前端百科全书网络专题之http2/http3

大前端百科全书,前端界的百科全书,记录前端各相关领域知识点,方便后续查阅及面试准备

关键词

关键词:多路复用、二进制分帧层、header压缩、服务端push、QUIC(基于UDP协议)

  • 说一下 http2 的特性,http2 怎么确保文件同时传输不会报错?
  • HTTP2.0 的多路复用和 HTTP1.x 中的长连接复用有什么区别?

HTTP1和HTTP1.1的区别

管线化、持久化连接、对头阻塞、

HTTP/1.0每进行一次HTTP通信,都需要经历建立TCP连接、传输HTTP数据和断开TCP连接三个阶段(如下图)。

image.png

持久化连接

在当时,由于通信的文件比较小,而且每个页面的引用也不多,所以这种传输形式没什么大问题。但是随着浏览器普及,单个页面中的图片文件越来越多,有时候一个页面可能包含了几百个外部引用的资源文件,如果在下载每个文件的时候,都需要经历建立TCP连接、传输数据和断开连接这样的步骤,无疑会增加大量无谓的开销。 为了解决这个问题,HTTP/1.1中增加了持久连接的方法,它的特点是在一个TCP连接上可以传输多个HTTP 请求,只要浏览器或者服务器没有明确断开连接,那么该TCP连接会一直保持。

持久连接在HTTP/1.1中是默认开启的,所以你不需要专门为了持久连接去HTTP请求头设置信息,如果你不想要采用持久连接,可以在HTTP请求头中加上**Connection: close(默认为Connection:keep-alive)****。**目前浏览器中对于同一个域名,默认允许同时建立6个TCP持久连接

管线化

持久连接虽然能减少TCP的建立和断开次数,但是它需要等待前面的请求返回之后,才能进行下一次请求。如果TCP通道中的某个请求因为某些原因没有及时返回,那么就会阻塞后面的所有请求,这就是著名的队头阻塞的问题。

HTTP/1.1中试图通过管线化的技术来解决队头阻塞的问题。HTTP/1.1中的管线化是指将多个HTTP请求整批提交给服务器的技术,虽然可以整批发送请求,不过服务器依然需要根据请求顺序来回复浏览器的请求。FireFox、Chrome都做过管线化的试验,但是由于各种原因,它们最终都放弃了管线化技术。

提供虚拟主机的支持

在HTTP/1.0中,每个域名绑定了一个唯一的IP地址,因此一个服务器只能支持一个域名。但是随着虚拟主机技术的发展,需要实现在一台物理主机上绑定多个虚拟主机,每个虚拟主机都有自己的单独的域名,这些单独的域名都公用同一个IP地址。 因此,HTTP/1.1的请求头中增加了Host字段,用来表示当前的域名地址,这样服务器就可以根据不同的Host值做不同的处理。

改进和优化

我们知道HTTP/1.1为网络效率做了大量的优化,最核心的有如下三种方式:

1.  增加了持久连接;
2.  浏览器为每个域名最多同时维护6个TCP持久连接; 
3.  使用CDN的实现域名分片机制。
复制代码

http2

HTTP/2的解决方案可以总结为:一个域名只使用一个TCP连接和消除队头阻塞问题

http3

QUIC协议(全称Quick UDP Internet Connections,快速UDP互联网连接)

HTTP/2存在一些比较严重的与TCP协议相关的缺陷,但由于TCP协议僵化,我们几乎不可能通过修改TCP协 议自身来解决这些问题,那么解决问题的思路是绕过TCP协议,发明一个TCP和UDP之外的新的传输协议。

但是这也面临着和修改TCP一样的挑战,因为中间设备的僵化,这些设备只认TCP和UDP,如果采用了新的 协议,新协议在这些设备同样不被很好地支持。

因此,HTTP/3选择了一个折衷的方法——UDP协议,基于UDP实现了类似于 TCP的多路数据流、传输可靠性等功能,我们把这套功能称为QUIC协议。关于HTTP/2和HTTP/3协议栈的比较,你可以参考下图:

通过上图我们可以看出,HTTP/3中的QUIC协议集合了以下几点功能。

  • 实现了类似TCP的流量控制、传输可靠性的功能。虽然UDP不提供可靠性的传输,但QUIC在UDP的基础 之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些TCP中存在的特性。
  • 集成了TLS加密功能。目前QUIC使用的是TLS1.3,相较于早期版本,TLS1.3有更多的优点,其中最重要的 一点是减少了握手所花费的RTT个数。
  • 实现了HTTP/2中的多路复用功能。和TCP不同,QUIC实现了在同一物理连接上可以有多个独立的逻辑数 据流(如下图)。实现了数据流的单独传输,就解决了TCP中队头阻塞的问题。

  • 实现了快速握手功能。由于QUIC是基于UDP的,所以QUIC可以实现使用0-RTT或者1-RTT来建立连接, 这意味着QUIC可以用最快的速度来发送和接收数据,这样可以大大提升首次打开⻚面的速度。

HTTP/3的挑战

通过上面的分析,我们相信在技术层面,HTTP/3是个完美的协议。不过要将HTTP/3应用到实际环境中依然 面临着诸多严峻的挑战,这些挑战主要来自于以下三个方面。

第一,从目前的情况来看,服务器和浏览器端都没有对HTTP/3提供比较完整的支持。Chrome虽然在数年前 就开始支持Google版本的QUIC,但是这个版本的QUIC和官方的QUIC存在着非常大的差异。

第二,部署HTTP/3也存在着非常大的问题。因为系统内核对UDP的优化远远没有达到TCP的优化程度,这 也是阻碍QUIC的一个重要原因。

第三,中间设备僵化的问题。这些设备对UDP的优化程度远远低于TCP,据统计使用QUIC协议时,大约有 3%〜7%的丢包率。

说一下 http2 的特性,http2 怎么确保文件同时传输不会报错?

  • 二进制传输
  • 多路复用

二进制传输

在之前的 HTTP 中,是通过文本传输的,在 HTTP2 中所有的传输数据都会被分割,并采用二进制格式编码

多路复用

在 HTTP2 中有两个概念,分别是stream(流)frame(帧),frame 是最小的单位,每个 frame 会有 stream Identifier 来标明它是属于哪个 stream 的

在 HTTP1.x 情况下,每个 http 请求都会建立一个 tcp 连接,也就意味着每个请求都要进行三次握手,这会造成时间和资源的浪费,而且浏览器会限制同一域名下并发请求的个数,当请求很多资源的时候,队头阻塞会导致在达到最大请求数量时,剩余的资源要等待其他资源请求完成才能发起请求(在这里说一下针对这种情况的优化手段,就是把不同资源放在不同域名下,以此来突破浏览器最大并发数的限制)

同一个tcp连接下多个http请求,如何保证传输不会出错呢?

多路复用就是在一个 tcp 连接中可以存在多个 stream,也就是多个请求,每个stream又包含了多个frame,通过stream Identifier就可以识别出每个frame分别对应的stream,当frame到达服务端之后,就可以根据stream Identifier 来重新组合得到完整的请求了,这就在提高传输性能的同时保证了传输的正确性。

Header压缩

HTTP1.x中使用文本的形式传输header,每次请求都会带上,这些基本上都是不变的,如果再加上cookie的话也是不小的浪费

HTTP2中,使用了HPACK 压缩格式对header进行编码,减少了header的大小,大概原理是在服务端和客户端共同维护一个静态字典,用于记录出现过的header,后面在传输过程中发送端直接传输已经记录过的键名,接收端就可以通过键名找到对应的值

服务端push

在HTTP2中,服务端可以在客户端的某个请求后,根据这个请求,主动推送其它的资源

比如一个html页面中还带上一个css和js的资源请求,HTTP1.x的时候,要发送三次请求,在HTTP2中,不用请求三次,服务器发现html中包含了css和js资源,便会将三个资源都返回给客户端,这样只需要一次通信,就可以获得全部资源。

HTTP2.0 的多路复用和 HTTP1.x 中的长连接复用有什么区别?

  • HTTP/1.X :默认开启持久连接,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。

  • HTTP/2.0 :支持多路复用,这是 HTTP/1.x 持久连接的升级版。多路复用,就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,服务端则可以通过帧中的标识知道该帧属于哪个流(即请求),通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能

  • HTTP/1.* 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接;
  • HTTP/1.1 Pipeling解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞
  • HTTP/2.0 支持多路复用,这是 HTTP/1.x 持久连接的升级版。多路复用,就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,服务端则可以通过帧中的标识知道该帧属于哪个流(即请求),通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了线头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能

image.png

文章分类
前端
文章标签