跳至主要內容

HTTP - 状态码、头部


HTTP 基本概念

HTTP 是什么?

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

  1. 「协议」:HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者),以及相关的各种控制和错误处理方式(行为约定和规范)。
  2. 「传输」:HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。
  3. 「超文本」:HTTP 传输的内容是「超文本」。

「文本」在互联网早期的时候只是简单的字符文字,但现在「文本」的涵义已经可以扩展为图片、视频、压缩包等,在 HTTP 眼里这些都算作「文本」。

「超文本」,就是超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。

HTML 就是最常见的超文本了,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,再经过浏览器的解释,呈现给我们的就是一个文字、有画面的网页了。

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

那「HTTP 是用于从互联网服务器传输超文本到本地浏览器的协议」,这种说法正确吗?
这种说法是不正确的。因为也可以是「服务器< -- >服务器」,所以采用两点之间的描述会更准确。

HTTP报文组成

HTTP报文是简单的格式化数据块,每条报文都包含一条来自客户端的请求,或者一条来自服务器的响应。它们由三个部分组成:对报文进行描述的起始行、包含属性的首部块、以及可选的、包含数据的主题部分。

起始行和首部就是由行分隔的 ASCII文本。每行都以一个由2个字符组成的行终止序列作为结束,包括一个回车符(ASCII码13)和一个换行符(ASCII码10)即"\r\n",这个行终止序列可以写为CRLF。(稳健的应用程序也应该接受单个换行符作为行的终止)

实体的主体和报文的主体是一个可选的数据块。与起始行和首部不同的是,主体中可包含文本或二进制数据,也可以为空。

请求报文

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成

  • 请求行(Request Line):

    • 方法:如 GET、POST、PUT、DELETE等,指定要执行的操作。
    • 请求 URI(统一资源标识符):请求的资源路径,通常包括主机名、端口号(如果非默认)、路径和查询字符串。
    • HTTP 版本:如 HTTP/1.1 或 HTTP/2。

    请求行的格式示例:GET /index.html HTTP/1.1

  • 请求头(Request Headers):

    • 包含了客户端环境信息、请求体的大小(如果有)、客户端支持的压缩类型等。
    • 常见的请求头包括HostUser-AgentAcceptAccept-EncodingContent-Length等。
  • 空行

    • 请求头和请求体之间的分隔符,表示请求头的结束。
  • 请求体(可选):

    • 在某些类型的HTTP请求(如 POST 和 PUT)中,请求体包含要发送给服务器的数据。

响应报文

HTTP 响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

  • 状态行(Status Line):

    • HTTP 版本:与请求消息中的版本相匹配。
    • 状态码:三位数,表示请求的处理结果,如 200 表示成功,404 表示未找到资源。
    • 状态信息:状态码的简短描述。

    状态行的格式示例:HTTP/1.1 200 OK

  • 响应头(Response Headers):

    • 包含了服务器环境信息、响应体的大小、服务器支持的压缩类型等。
    • 常见的响应头包括Content-TypeContent-LengthServerSet-Cookie等。
  • 空行

    • 响应头和响应体之间的分隔符,表示响应头的结束。
  • 响应体(可选):

    • 包含服务器返回的数据,如请求的网页内容、图片、JSON数据等。

HTTP 常见的状态码

五大类 HTTP 状态码

1xx

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

比如协议转换,从HTTP转换成Websocket就是用的101状态码

2xx

表示服务器成功处理了客户端的请求

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

3xx

表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。

  • 「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。
  • 「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。
  • 「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。

4xx

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

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

5xx

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

  • 「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
  • 「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
  • 「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
  • 「503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思。

HTTP常见方法

根据 HTTP 标准,HTTP 请求可以使用多种请求方法。

HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。

HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。

序号方法描述
1GET用于请求服务器发送某个资源。GET 请求不应该对服务器上的资源做出任何更改,并且应该是幂等的(即多次重复的请求应该产生相同的结果)。例如,当你在浏览器中输入 URL 地址时,浏览器会发送一个 GET 请求来获取该 URL 对应的网页。
2HEAD类类似于 GET 请求,但服务器不返回请求的资源主体,只返回响应头。HEAD 请求通常用于获取资源的元信息,如资源的大小、类型等,而不需要获取资源的实际内容。
3POST用于向服务器提交数据,通常用于提交表单或上传文件。POST 请求可能会导致服务器上的状态更改,并且不一定是幂等的。例如,在提交注册表单时,浏览器通常会发送一个 POST 请求,将用户提供的信息发送到服务器进行处理。
4PUT用于向服务器上传资源,通常用于更新已存在的资源或创建新的资源。PUT 请求应该是幂等的,即多次执行相同的 PUT 请求应该产生相同的结果。
5DELETE用于请求服务器删除指定的资源。DELETE 请求应该是幂等的,即多次执行相同的 DELETE 请求应该产生相同的结果。
6CONNECT用于建立到服务器上指定端口的隧道,通常用于代理服务器。
7OPTIONS用于请求服务器返回支持的 HTTP 方法和其他选项。例如,客户端可以发送 OPTIONS 请求来确定服务器支持哪些 CORS(跨域资源共享)策略。
8TRACE回显服务器收到的请求,主要用于测试或诊断。
9PATCH用于在请求-响应链上的每个节点获取传输路径。TRACE 请求通常用于调试和测试,以查看请求在经过各种代理服务器和中间件时如何被修改。

GET 和 POST 的区别

功能不同:

  • get是从服务器上获取数据。
  • post是向服务器传送数据。

过程不同:

  • get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。
  • post请求携带数据的位置一般是写在报文 body 中,body 中的数据可以是任意格式的数据,只要客户端与服务端协商好即可

GET 请求可以带 body 吗?
RFC 规范并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。只是因为 RFC 规范定义的 GET 请求是获取资源,所以根据这个语义不需要用到 body。
另外,URL 中的查询参数也不是 GET 所独有的,POST 请求的 URL 中也可以有参数的。

传送数据量不同:

  • get传送的数据量较小,不能大于2KB。
  • post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。

安全性:

  • get安全性非常低。
  • post安全性相对较高。

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

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

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

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

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

HTTP 常见字段

Host 字段

客户端发送请求时,用来指定服务器的域名。

Content-Length 字段

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

比如Content-Length: 1000 就是告诉浏览器,本次服务器回应的数据长度是 1000 个字节,后面的字节就属于下一个回应了。

HTTP 是基于 TCP 传输协议进行通信的,而使用了 TCP 传输协议,就会存在一个“粘包”的问题,HTTP 协议通过设置回车符、换行符作为 HTTP header 的边界,通过 Content-Length 字段作为 HTTP body 的边界,这两个方式都是为了解决“粘包”的问题。

Connection 字段

Connection 字段最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用。

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

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

  • Connection: Keep-Alive

开启了 HTTP Keep-Alive 机制后, 连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接,一直持续到客户端或服务器端提出断开连接。

Content-Type 字段

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

比如 Content-Type: text/html; Charset=utf-8 就表明,发送的是网页,而且编码是UTF-8。

Accept: /

客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。

/ 就表示客户端声明自己可以接受任何格式的数据。

Content-Encoding 字段

Content-Encoding 字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式

比如 Content-Encoding: gzip 就表示服务器返回的数据采用了 gzip 方式压缩,告知客户端需要用此方式解压。

Accept-Encoding 字段则说明客户端在请求时,表示客户端可以接受哪些压缩方法。

Accept-Encoding: gzip, deflate

其他字段介绍

HTTP的连接方式和无状态性

短连接

即浏览器每请求一个Web文档,就创建一个新的连接,当文档传输完毕后,连接就立刻被释放。

HTTP1.0、HTTP0.9采用此连接方式。

对于请求的Web页中包含多个其他文档对象(如图像、声音、视频等)的链接的情况,由于请求每个链接对应的文档都要创建新连接,效率低下。

长连接

即在一个连接中,可以进行多次文档的请求和响应。服务器在发送完响应后,并不立即释放连接,浏览器可以使用该连接继续请求其他文档。连接保持的时间可以由双方进行协商。

HTTP/1.1 版本的默认连接都是长连接,但为了兼容老版本的 HTTP,需要指定Connection: Keep-Alive

无状态性

是指同一个客户端(浏览器)第二次访问同一个Web服务器上的页面时,服务器无法知道这个客户曾经访问过。HTTP的无状态性简化了服务器的设计,使其更容易支持大量并发的HTTP请求。

对于无状态的问题,比较简单的方式用 Cookie 技术。

Cookie的安全问题

跨站脚本攻击(XSS):攻击者会利用XSS来窃取Cookie
会话管理不当:会话退出后没有注销、会话有效时间过长、重置或修改密码后未清除旧会话和会话能够被异地重放

Cookie的跨域问题

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域

Nginx反向代理:在一个服务器上配置多个前缀来转发http/https请求到多个真实的服务器即可
Java代码添加注解:@CrossOrigin(origins = "http://www.example.com")

HTTP 缓存技术

对于一些具有重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了。

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

强制缓存

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

如下图,返回的是 200 状态码,但在 size 项中标识的是 from disk cache,就是使用了强制缓存。

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

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

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

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

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

协商缓存

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

上图就是一个协商缓存的过程,所以协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。

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

  1. 通过请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现
    • 响应头部中的 Last-Modified(服务端返回的):标示这个响应资源的最后修改时间;
    • 请求头部中的 If-Modified-Since(客户端请求的):客户端发现发现响应头中具有 Last-Modified 声明,则发起请求的时候就会将请求头部中的 If-Modified-Since的值 设置为 Last-Modified 的时间,服务器收到请求后发现有 If-Modified-Since ,就与被请求资源的最后修改时间进行对比,如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 走缓存。
  2. 通过请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段,这两个字段的意思是:
    • 响应头部中 Etag(服务端返回的):唯一标识响应资源;
    • 请求头部中的 If-None-Match(客户端请求的):浏览器发现响应头里有 Etag,则向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200。

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

如果在第一次请求资源的时候,服务端返回的 HTTP 响应头部同时有 Etag 和 Last-Modified 字段,那么客户端再下一次请求的时候,如果带上了 ETag 和 Last-Modified 字段信息给服务端,这时 Etag 的优先级更高,也就是服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不用在判断 Last-Modified 了,如果 Etag 没有变化,然后再看 Last-Modified。

为什么 ETag 的优先级更高?这是因为 ETag 主要能解决 Last-Modified 几个比较难以解决的问题:

  1. 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求;
  2. 可能有些文件是在秒级以内修改的,If-Modified-Since 能检查到的粒度是秒级的,使用 Etag就能够保证这种需求下客户端在 1 秒内能刷新多次;
  3. 有些服务器不能精确获取文件的最后修改时间。

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

下图是强制缓存和协商缓存的工作流程:

当使用 ETag 字段实现的协商缓存的过程:

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

HTTP 特性

到目前为止,HTTP 常见到版本有 HTTP/1.1,HTTP/2.0,HTTP/3.0,不同版本的 HTTP 特性是不一样的。

HTTP/1.1 的优点

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

  1. 简单
    • HTTP 基本的报文格式就是 header + body,头部信息也是 key-value 简单文本的形式,易于理解,降低了学习和使用的门槛。
  2. 灵活和易于扩展
    • HTTP 协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。
    • 同时 HTTP 由于是工作在应用层( OSI 第七层),则它下层可以随意变化,比如:
      • HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层;
      • HTTP/1.1 和 HTTP/2.0 传输协议使用的是 TCP 协议,而到了 HTTP/3.0 传输协议改用了 UDP 协议。
  3. 应用广泛和跨平台
    • 互联网发展至今,HTTP 的应用范围非常的广泛,从台式机的浏览器到手机上的各种 APP,从看新闻、刷贴吧到购物、理财、吃鸡,HTTP 的应用遍地开花,同时天然具有跨平台的优越性。

HTTP/1.1 的缺点

HTTP 协议里有优缺点一体的双刃剑,分别是「无状态、明文传输」

  1. 无状态
    • 无状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务。
    • 无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。
      • 例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。
      • 这样每操作一次,都要验证信息,这样的购物体验还能愉快吗?别问,问就是酸爽!
    • 对于无状态的问题,解法方案有很多种,其中比较简单的方式用 Cookie 技术。
      • Cookie 通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。
  2. 不安全
    • 通信使用明文(不加密),内容可能会被窃听。比如,账号信息容易泄漏
    • 不验证通信方的身份,因此有可能遭遇伪装。比如,访问假的淘宝、拼多多
    • 无法证明报文的完整性,所以有可能已遭篡改。比如,网页上植入垃圾广告

HTTP 的安全问题,可以用 HTTPS 的方式解决,也就是通过引入 SSL/TLS 层。

正向代理和反向代理的区别

正向代理和反向代理在网络通信中扮演着不同的角色,它们之间有许多显著的区别:

正向代理:

  1. 定义: 正向代理是为了帮助客户端访问无法直接访问的服务器资源而设置的代理服务器。
  2. 作用对象: 正向代理的对象是客户端,代理服务器帮助客户端与目标服务器进行通信和数据交换。
  3. 安全性: 在正向代理中,客户端知道目标服务器的IP地址和端口号等敏感信息,而目标服务器不知道真正的客户端身份,存在一定的安全风险。
  4. 典型应用: 正向代理常用于为内部局域网客户端提供访问互联网的途径,以及实现缓存和权限验证等功能

反向代理:

  1. 定义: 反向代理是位于服务器端的代理服务器,接收客户端的请求,并将请求转发给内部的目标服务器/网站。
  2. 作用对象: 反向代理的对象是服务器/网站,为服务器提供负载均衡、安全防护等功能。
  3. 隐藏信息: 在反向代理中,客户端只知道代理服务器的地址,不知道真实的服务器是谁,从而保护了服务器的IP地址和其他敏感信息。
  4. 典型应用: 反向代理常用于隐藏真实服务器的结构和部署信息,提高系统的安全性,并用于实现多服务器间的负载均衡

HTTP/1.1 的性能

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

  1. 长连接
    • 早期 HTTP/1.0 性能上的一个很大的问题,那就是每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。
    • 为了解决上述 TCP 连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
    • 持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。如果某个 HTTP 长连接超过一定时间没有任何数据交互,服务端也会主动断开这个连接。
  2. 管道网络传输(默认不使用)
    • HTTP/1.1 采用了长连接的方式,这使得管道(pipeline)网络传输成为了可能。
      • 即可在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
      • 举例来说,客户端需要请求两个资源。以前的做法是,在同一个 TCP 连接里面,先发送 A 请求,然后等待服务器做出回应,收到后再发出 B 请求。那么,管道机制则是允许浏览器同时发出 A 请求和 B 请求,如下图:
    • 但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。
      如果服务端在处理 A 请求时耗时比较长,那么后续的请求的处理都会被阻塞住,这称为「队头堵塞」。
      • 所以,HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞。
  3. 队头阻塞
    • 当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据,这也就是「队头阻塞」。
seven97官方微信公众号
seven97官方微信公众号