【计算机网络】关于HTTP的常见问题

1.HTTP基本概念

Http是什么?

HTTP是超文本传输协议,也就是HyperText Transfer Protocol.

超文本传输协议

它可以拆分成三个部分:

  • 超文本
  • 传输
  • 协议

1.协议:HTTP是一个用在计算机世界的协议,它使用计算机能够理解的语言确立一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。

2.传输

所谓的传输,很好理解,就是把一堆东西从A点搬到B点,或者从B点搬到A点。所以,HTTP是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。

3.超文本

HTTP传输的内容是超文本。HTTP是一个在计算机专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。

HTTP常见的状态码有哪些?

1xx类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。

2xx类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

  • 200 OK 表示一切正常。
  • 204 NO Content 也是常见的成功状态码,与200 ok基本相同,但响应头没有body数据。
  • 206 Partial Content是应用于HTTP分块下载或断电续传,表示响应返回的body数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3xx类状态码表示客户端请求的资源发成了变动,需要客户端用心的URL重新发送请求获取资源,也就是重定向。

  • 301 Moved Permanently 表示永久重定向,说明请求的资源已经不存在了,需改用新的URL再次访问。
  • 302 Found 表示临时重定向,说明请求的资源还在,但暂时需要用另一个URL来访问。
  • 304 Not Modified 不具有跳转的含义,表示资源未修改,重定向已存在的缓存文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。

301和302都会在响应头里使用字段Location,指明后续要跳转的URL,浏览器会自动重定向新的URL。

4xx类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。

  • 400Bad Request 表示客户端请求的报文有错误,但只是个笼统的错误。
  • 403 Forbidden表示服务器禁止访问资源,并不是客户端的请求出错。
  • 404 Not Found表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。

5xx类状态码表示客户端请求报文正确,但是服务器处理时内部发生了什么错误,属于服务器端的错误码。

  • 500 Internal ServerError 与400类似,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
  • 501 Not Implemented 表示客户端请求的功能还不支持。
  • 502 Bad Gateway 通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
  • 503 Service Unavailable 表示服务器当前很忙,暂时无法相应客户端。

HTTP 常见字段有哪些?

host字段

客户端发送请求时,用来指定服务器的域名。 例如:www.a.com

Content-Length字段

服务器返回数据时,会有Content-Length字段,表明本次回应的数据长度。

Connection字段

Connection字段最常用于客户端要求服务器使用TCP持久连接,以便其它请求复用。

HTTP/1.1版本的默认连接都是持久连接,但为了兼容老版本的HTTP,需要指定Connection首部字段的值为Keep-Alive.

一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段。

Content-Type字段

Content-Type字段用于服务器回应时,告诉客户端,本次数据时什么格式。如:Accept:"/"

Content-Encoding字段

Content-Encoding字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。比如:Accept-Encoding:gzip,deflate; Content-Encoding:gzip

GET与POST

根据RFC规范,GET的语义是从服务器获取指定的资源,这个资源可以是静态的文本、页面、图片视频等。GET请求的参数位置一般是写在URL中URL规定只能支持ASCII,所以GET请求的参数只允许ASCII字符,而且浏览器会对URL的长度有限制(HTTP协议本身对URL长度并没有做任何规定)。

根据RFC规范,POST的语义是根据请求负荷(报文body)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST请求携带数据的位置一般是写在报文body中body中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对body大小做限制

GET和POST方法都是安全和幂等的么?

先说明下安全和幂等的概念:

  • 在HTTP协议里,所谓的安全是指请求方法不会破坏服务器上的资源。
  • 所谓的幂等,意思是多次执行相同的操作,结果都是相同的。

如果从RFC规范定义的语义来看:

  • GET方法就是安全且幂等的,因为它是只读操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对GET请求的数据做缓存,这个缓存可以做到浏览器本身上,也可以做到代理上(如nginx),而且在浏览器中GET请求可以保存为书签。
  • POST因为是新增或提交数据的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的,所以,浏览器一般不会缓存POST请求,不能把POST请求保存为书签。

但在实际的开发过程,开发者不一定会按照RFC规范定义的语义来实现GET和POST方法。比如:

  • 可以用GET方法实现新增或删除数据的请求,这样实现的GET方法自然就不是安全和幂等。
  • 可以用POST方法实现查询数据的请求,这样的实现的POST方法自然就是安全和幂等。

如果安全放入概念是指信息是否会被泄漏的话,虽然POST用body传输数据,而GET用URL传输,这用数据会再浏览器地址栏容易看到,但是并不能说GET不如POST安全的。

因为HTTP传输的内容都是明文的,虽然在浏览器地址看不到POST提交的body数据,但是只要抓个包就都能看到了。

所以,要避免传输过程中的内容被窃取,就要使用HTTPS协议,这样所有HTTP的数据都会被加密传输。

GET请求可以带body么?

RFC规范并没有规定GET请求不能带body的。理论上,任何请求都可以带body的。只是因为RFC规范定义的GET请求是获取资源,所以根据这个语义不需要用到body。

另外,URL中的查询参数也不是GET所独有的。POST请求的URL中也可以有参数的。

HTTP缓存技术


HTTP缓存有哪些实现方式?

对于一些具有重复性的HTTP请求,比如每次请求得到的数据都一样的,我们可以把这对【请求-相应】的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应,这样的话HTTP/1.1的性能肯定肉眼可见的提升。

所以,避免发送HTTP请求的方法就是通过缓存技术,HTTP设计者早在之前就考虑到了这点,因此HTTP协议的头部有不少是针对缓存的字段。

HTTP缓存有两种实现方式,分别是强制缓存和协商缓存。

什么是强制缓存?

强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。

强缓存是利用下面这两个HTTP响应头部字段实现的,它们都用来表示资源在客户端缓存的有效期:

  • Cache-Control:是一个相对时间;
  • Expires:是一个绝对时间;

如果HTTP响应头部同时有Cache_Control和Expires字段的话,Cache-Control的优先级高于Expires。

Cache-control选项更多一些,设置更加精细,所以建议使用Cache-Control来实现强缓存。具体的实现流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头部加上Cache-Control,Cache-Control中设置了过期时间大小。
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与Cache-Control中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  • 服务器再次收到请求后,会再次更新Response头部的Cache-Control.

什么是协商缓存?

当我们在浏览器使用开发者工具的时候,你可能会看到过某些请求的响应码是304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。

协商缓存可以基于两种头部来实现。

第一种:请求头部中的If-Modified-Since字段与响应头部中的Last-Modified字段实现,这两个字段的意思是:

  • 响应头部中的Last_Modified:表示这个相应资源的最后修改时间;
  • 请求头部的If-Modified-Since:当资源过期了,发现响应头中具有Last_Modified声明,则再次发起请求的时候带上Last-Modified的时间,服务器收到请求后发现有If-Modified-Since则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应HTTP304走缓存。

第二种:请求头部中的If-None-Match字段与响应头部中的ETA字段,这两个字段的意思是:

  • 响应头部的Etag:唯一标识响应资源;
  • 请求头部中的If-None-Match:当资源过期时,浏览器发现响应头里有Etag,则再次向服务器发起请求,会将请求If-None-Match值设置为Etag的值。服务器收到请求后进行对比,如果资源没有变化返回304,如果资源变化了返回200.

第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者可以更为准确地判断文件是否被修改,避免由于时间篡改导致的不可靠问题。

如果HTTP响应头部同时有Etag和Last-Modified字段的时候,Etag的优先级更高,也就是先会判断Etag是否变花了,如果Etag没有变化,然后再看Last-Modified。

注意,协商缓存着两个字段都需要配合强制缓存中Cache-control字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。

使用Etag字段实现的协商缓存的过程如下:

  • 当浏览器第一次请求访问服务器时,服务器会在返回这个资源的同时,在Response头部加上Etag唯一标识,这个唯一标识的值是根据当前请求的资源生成的;
  • 当浏览器再次请求访问服务器中的该资源时,首先会先检查强制缓存是否过期,如果没有过期,则直接使用本地缓存;如果缓存过期了,会在Request头部加上If-None-Match字段,该字段的值就是ETag唯一标识;
  • 服务器再次收到请求后,会根据请求中的If-None-Match值与当前请求的资源生成的唯一标识进行比较:
    • 如果值相等,则返回304 Not Modified,不会返回资源;
    • 如果不相等,则返回200状态码和返回资源,并在Response头部加上新的Etag唯一标识;
  • 如果浏览器收到304的请求相应状态码,则会从本地缓存中加载资源,否则更新资源。

HTTP特性


HTTP(1.1)的优点有哪些?

HTTP最突出的优点是简单、灵活和易于扩展、应用广泛和跨平台。

1.简单

HTTP基本的报文格式就是header+body,头部信息也是key-value简单文本的形式,易于理解,降低了学习和使用的门槛。

2.灵活和易于扩展

HTTP协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。

同时HTTP由于是工作在应用层(OSI第七层),它下层可以随意变化。

HTTPS也就是在HTTP与TCP层之间增加了SSL/TLS安全传输层,HTTP/3甚至把TCP层换成了基于UDP的QUIC。

3.应用广泛和跨平台

互联网发展至今,HTTP的应用范围非常的广泛,从台式机的浏览器到手机上的各种APP,从新闻、刷贴吧到购物、理财,HTTP的应用遍地开花,同时天然具有跨平台的优越性。

HTTP(1.1)的缺点有哪些?

HTTP协议里有优缺点一体的双刃剑,分别是无状态、明文传输,同时还有一大缺点不安全。

1.无状态双刃剑

无状态的好处,因为服务器不会去记忆HTTP的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的CPU和内存用来对外提供服务。

无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。

例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。

对于无状态的问题,解决办法有很多种,其中比较简单的方式用cookie技术。

Cookie通过在请求和相应报文中写入Cookie信息来控制客户端的状态。

相当于,在客户端第一次请求后,服务器会下发一个装有客户信息的小贴纸,后续客户端请求服务器的时候,带上小贴纸,服务器就能认得了。

2.明文传输双刃剑

明文意味着在传输过程中的信息,是可方便阅读的,通过浏览器的F12控制台或Wireshark抓包都可以直接肉眼查看,为我们调试工作带了极大的便利性。

但正是这样,HTTP的所有信息都暴露在了光天化日下,相当于信息裸奔。在传输的漫长过程中,信息的内容都毫无隐私可言,很容易就能被窃取,如果里面有你的账号信息密码,容易被窃取。

3. 不安全

HTTP比较严重的缺点就是不安全:

  • 通信使用明文,内容可能会被窃听。
  • 不验证通信方的身份,因此有可能遭遇伪装。
  • 无法证明报文的完整性,所以有可能已遭篡改。

HTTP的安全问题,可以用HTTPS的方式解决,也就是通过引入SSL/TLS层,使得在安全上达到了极致。

HTTP/1.1的性能如何?

HTTP协议是基于TCP/IP,并且使用了请求-应答的通信模式,所以性能的关键就在于这两点。

1.长连接

早期HTTP/1.0性能上的一个很大的问题,那就是每发起一个请求,都要新建一次TCP连接(三次握手),而且是串行请求,做了无谓的TCP连接建立和断开,增加了通信开销。

为了解决上述TCP连接问题,HTTP/1.1提出了长连接的通信方式,也叫持久连接。这种通信方式的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器的负载。

持久连接的特点是,只要任意一端没有明确提出断开连接,则保持TCP连接状态。

当然,如果某个HTTP长连接超过一定时间没有任何数据交互,服务端就会主动断开这个连接。

2.管道网络传输

HTTP/1.1采用了长连接的方式,这使得管道网络传输成为了可能。

即可在同一个TCP连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。

如果服务端在处理A请求时耗时比较长,那么后续的请求的处理都会被阻塞住,这称为队头阻塞。所以,HTTP/1.1管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞。

3.队头阻塞

「请求 - 应答」的模式加剧了 HTTP 的性能问题。

因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据,这也就是「队头阻塞」,好比上班的路上塞车。

总之 HTTP/1.1 的性能一般般,后续的 HTTP/2 和 HTTP/3 就是在优化 HTTP 的性能。

HTTP与HTTPS


HTTP与HTTPS有哪些区别?

1.HTTP是超文本传输协议,信息是明文传输,存在安全风险的问题。HTTPS则解决了HTTP不安全的缺陷,在TCP和HTTP网络层之间加入了SSL/TLS安全协议,使得报文能够加密传输。

2.HTTP连接建立相对简单,TCP三次握手之后便可进行HTTP的报文传输。而HTTPS在TCP三次握手之后,还需要进行SSL/TLS的握手过程,才可进入加密报文传输。

3.HTTP的端口号是80,HTTPS的端口号是443.

4.HTTPS的协议需要向CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。

HTTPS解决了HTTP的哪些问题?

HTTP由于是明文传输,所以安全上存在以下三个风险:

  • 窃听风险,比如通信链路上可以获取通信内容,用户号容易丢失。
  • 篡改风险,比如强制植入垃圾广告。
  • 冒充风险,比如冒充淘宝网站。

HTTPS在HTTP与TCP层之间加入了SSL/TLS协议,可以很好的解决上述问题:

  • 信息加密:交互信息无法被窃取。
  • 校验机制:无法篡改通信内容,篡改了就不能正常显示。
  • 身份证书:证明淘宝是真的淘宝。

HTTPS是如何解决上面的三个风险的?

  • 混合加密的方式实现信息的机密性,解决了窃听的风险。
  • 摘要算法的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
  • 将服务器公钥放入到数字证书中,解决了冒充的风险。

1.混合加密

HTTPS 采用的是对称加密非对称加密结合的「混合加密」方式:

  • 在通信建立前采用非对称加密的方式交换「会话秘钥」,后续就不再使用非对称加密。
  • 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。

采用「混合加密」的方式的原因:

  • 对称加密只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。
  • 非对称加密使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢。

2. 摘要算法

摘要算法用来实现完整性,能够为数据生成独一无二的「指纹」,用于校验数据的完整性,解决了篡改的风险。

客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹 + 明文」一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。

3. 数字证书

客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。

这就存在些问题,如何保证公钥不被篡改和信任度?

所以这里就需要借助第三方权威机构 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。

图1 获取数字证书过程

通过数字证书的方式保证服务器公钥的身份,解决冒充的风险。

 HTTPS 是如何建立连接的?其间交互了什么?

SSL/TLS协议的基本流程:

  • 客户端向服务端索要并验证服务器的公钥。
  • 双方协商生产会话秘钥。
  • 双方采用会话秘钥进行加密通信。

前两步就是SSL/TLS的建立过程,也就是TLS握手阶段。

SSL/TLS的握手阶段涉及四次通信。

 图2 SSL/TLS协议基本流程

SSL/TLS协议的详细流程:

1.ClientHello

首先,由客户端向服务器发起加密通信请求,也就是ClientHello请求。

在这一步,客户端主要向服务器发送一下信息:

  1. 客户端支持的SSL/TLS协议版本,如TLS 1.2版本。
  2. 客户端生产的随机数,后面用于生成会话秘钥条件之一。
  3. 客户端支持的密码套件列表,如RSA加密算法。

2.ServerHello

服务器收到客户端请求后,向客户端发出响应,也就是ServerHello。服务器回应的内容有如下内容:

  1. 确认SSL/TLS协议版本,如果浏览器不支持,则关闭加密通信。
  2. 服务器生产的随机数,也是后面用于生产会话秘钥条件之一。
  3. 确认的密码套件列表,如RSA加密算法。
  4. 服务器的数字证书。

3.客户端回应

客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的CA公钥,确认服务器的数字证书的真实性。

如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:

  1. 一个随机数(pre-master key)。该随机数会被服务器公钥加密。
  2. 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信。
  3. 客户端握手结束通知,表示客户端的我有阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供服务端校验。

上面第一项的随机数是整个握手阶段的第三个随机数,会发给服务端,所以这个随机数客户端和服务端都是一样的。

服务器和客户端有了这三个随机数(Client Random/ Server Random/ pre-master key),接着就用双方协商的加密算法,各自生成本次通信的会话秘钥。

4.服务器的最后回应

服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的会话秘钥。

然后,向客户端发送最后的信息:

  1. 加密通信算法改变通知,表示随后的信息都将用会话秘钥加密通信。
  2. 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时把之前所有内容的发生的数据做个摘要,用来供客户端校验。

至此,整个SSL/TLS的握手阶段全部结束。加下来,客户端与服务器进入解密通信,就完全是使用普通的HTTP协议,只不过用会话秘钥加密内容。

HTTP/1.1 HTTP/2 HTTP/3演变


HTTP/1.1相比HTTP/1.0提高了什么性能?

HTTP/1.1相比HTTP/1.0性能上的改进:

  • 使用TCP长连接的方式改善了HTTP/1.0短连接造成的性能开销。
  • 支持管道网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

但HTTP/1.1还是有性能瓶颈:

  • 请求、响应头部未经压缩就发送,首部信息越多延迟越大。只能压缩Body的部分;
  • 发送冗长的首部,每次互相发送相同的首部造成的浪费较多。
  • 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
  • 没有请求优先级控制;
  • 请求只能从客户端开始,服务器只能被动响应。

Http/2做了什么优化?

HTTP/2协议是基于HTTPS的,所以HTTP/2的安全性也是有保障的。

图3 HTTP协议对比

 1.头部压缩

HTTP/2会压缩头,如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。

这就是所谓的HPACK算法;在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样的字段了,只发送索引号,这样就提高速度了。

2.二进制格式

HTTP/2不再像HTTP/1.1里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧:头信息针和数据帧。

这样虽然对人不友好,因为计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需在将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率。

3.数据流

HTTP/2的数据包不是按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。

在HTTP/2中每个请求或相应的所有数据包,称为一个数据流。每个数据流都标记着一个独一无二的编号(Stream ID),不同Stream的帧是可以乱序发送的(因此可以并发不同的Stream),因为每个帧的头部会携带Stream ID信息,所以接收端可以通过Stream ID有序组装成HTTP消息。

客户端和服务端双方都可以建立Stream,Stream ID也是有区别的,客户端建立的Stream必须是奇数号,而服务器建立的Stream必须是偶数号。

客户端还可以指定数据流的优先级。优先级高的请求,服务器就先响应该请求。

4.多路复用

HTTP/2是可以在一个连接中并发多个请求或回应,而不用按照顺序一一对应。

移除了HTTP/1.1中的串行请求,不需要排队等待,也就不会在出现队头阻塞问题,降低了延迟,大幅度提高了连接的利用率。

举例来说,在一个TCP连接里,服务器收到了客户端A和B的两个请求,如果发现A处理过程非常耗时,于是就回应A请求已经处理好的部分,接着回应B请求,完成后,再回应A请求剩下的部分。

5.服务器推送

HTTP/2还在一定程度上改善了传统的请求-应答工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。

比如,客户端通过HTTP/1.1请求从服务器那里获取到了HTML文件,而HTML可能还需要依赖CSS来渲染页面,这个客户端还要再次发起获取CSS文件的请求,需要两次详细往返。但在HTTP/2中,客户端在访问HTML时,服务器可以直接主动推送CSS文件,减少了消息传递的次数。

HTTP/2有什么缺陷?

HTTP/2通过Stream的并发能力,解决了HTTP/1队头阻塞的问题,看似很完美了,但是HTTP/2还是存在队头阻塞的问题,只不过问题不是在HTTP这一层面,而是子TCP这一层。

HTTP/2是基于TCP协议来传输数据的,TCP是字节流协议,TCP层必须保证收到的字节是完整且连续的,这样内核才会将缓冲区里的数据返回给HTTP应用,那么当 前一个字节数据没有到达时,后收到的字节数据智能存放在内核缓冲区里,只有等到这1个字节数据到达时,HTTP/2应用层才能从内核中拿到数据,这就是HTTP/2队头阻塞问题。

所以,一旦发生了丢包现象,就会触发TCP的重传机制,这样在一个TCP连接中的所有的HTTP请求都必须等待这个丢了的包被重传回来。

HTTP/3做了哪些优化?

前面我们知道了HTTP/1.1和HTTP/2都有队头阻塞的问题:

  • HTTP/1.1中的管道(pipeline)虽然解决了请求的队头阻塞,但是没有解决响应的队头阻塞,因为服务端需要按顺序响应收到的请求,如果服务端处理某个请求消耗的时间比较长,那么只能等相应完这个请求后,才能处理下一个请求,这属于HTTP层队头阻塞。
  • HTTP/2虽然通过多个请求复用一个TCP连接解决eltHTTP的队头阻塞,但是一旦发生丢包,就会阻塞住所有的HTTP请求,这属于TCP层队头阻塞。

HTTP/2队头阻塞的问题是因为TCP,所以HTTP/3把HTTP下层的TCP协议改成了UDP!

 图4 HTTP协议对比

UDP发生是不管顺序的,也不管丢包的,所以不会出现像HTTP/2队头阻塞的问题

总所周知,UDP是不可靠传输,但基于UDP的QUIC协议可以实现类似TCP的可靠性传输。

QUIC有以下3个特点:

1.无队头阻塞

QUIC协议也有类似HTTP/2 Stream与多路复用的概念,也是可以在同一条连接上并发传输多个Stream,Stream可以认为就是一条HTTP请求。

QUIC有自己的一套机制可以保证传输的可靠性。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。这与HTTP/2不同,HTTP/2只要某个流中的数据包丢失了,其他流也会因此受到影响。

所以,QUIC连接上的多个Stream之间并没有依赖,都是独立的,某个流发生丢包了,只会影响该流,其他流不受影响。

2.更快的连接建立

对于HTTP/1和HTTP/2协议,TCP和TLS是分层的,分别属于内核实现的传输层、openssl库实现的表示层,因此它们难以合并在一次,需要分批次来握手,先TCP握手,再TLS握手。

HTTP/3在传输数据前虽然需要QUIC协议握手,这个握手过程只需要1RTT,握手的目的是为确认双方的 连接ID,连接迁移就是基于连接ID实现的。

但是HTTP/3的QUIC协议并不是与TLS分层,而是QUIC内部包含了TCL,它在自己的帧会携带TLS里的“记录”,再加上QUIC使用的TLS/1.3,因此仅需1个RTT就可以 同时完成建立连接与秘钥协商。

甚至,在第二次连接的时候,应用数据包可以和QUIC握手信息(连接信息+TLS信息)一起发送,达到0-RTT的效果。

3.连接迁移

基于TCP传输协议的HTTP协议,由于是通过四元组(源IP、源端口、目的IP、目的端口)确定一条TCP连接,那么当移动设备的网络从4G切换到WIFI时,意味着IP地址变化了,那么久必须要断开连接,然后重新建立连接。而建立连接的过程包含TCP握手和TLS四次握手的时延,以及TCP慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

而QUIC协议没有用四元组的方式来绑定连接,而是通过连接ID来标记通信的两个端点,客户端和服务器可以各自选择一组ID来标记自己,因此即使移动设备的网络变化后,导致IP地址变化了,只要仍保有上下文信息(比如连接ID、TLS秘钥等),就可以“无缝”地复用原连接成本,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

所以,QUIC是一个在UDP之上的伪TCP+TLS+HTTP/2的多路复用的协议。

QUIC是新协议,对于很多网络设备,根本不知道什么是QUIC,只会当做UDP,这样就会出现新的问题,因为有的网络设备实惠丢掉UDP包的,而QUIC是基于UDP实现的,那么如果网络设备无法识别这个是QUIC包,那么就会当做UDP包,然后被丢弃。

所以,HTTP/3现在普及的进度非常的缓慢,不知道未来UDP是否能够逆袭TCP。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值