likes
comments
collection
share

当面试官问我不同HTTP版本之间的差异

作者站长头像
站长
· 阅读数 12

报文格式

请求报文

当面试官问我不同HTTP版本之间的差异

除了上述信息外,一个请求还可能包括请求体,一些像 POST 这样的方法,请求体内包含了需要发送的资源。

响应报文

当面试官问我不同HTTP版本之间的差异

发展史

HTTP/0.9——单行协议

请求由单行指令构成,以唯一可用方法 GET 开头,其后跟目标资源的路径:GET /mypage.html

响应也极其简单的:只包含响应文档本身。HTTP/0.9 的响应内容并不包含 HTTP 头。这意味着只有 HTML 文件可以传送,无法传输其他类型的文件。也没有状态码或错误代码。一旦出现问题,一个特殊的包含问题描述信息的 HTML 文件将被发回,供人们查看。

HTTP/1.0——构建可扩展性

  • 协议版本信息现在会随着每个请求发送(HTTP/1.0 被追加到了 GET 行)。
  • 状态码会在响应开始时发送,使浏览器能了解请求执行成功或失败,并相应调整行为(如更新或使用本地缓存)。
  • 引入了 HTTP 标头的概念,无论是对于请求还是响应,允许传输元数据,使协议变得非常灵活,更具扩展性。
  • 在新 HTTP 标头的帮助下,具备了传输除纯文本 HTML 文件以外其他类型文档的能力(凭借 Content-Type标头)。

HTTP/1.1——标准化的协议

  • 连接可以复用,节省了多次打开 TCP 连接加载网页文档资源的时间。
  • 增加管线化技术,允许在第一个应答被完全发送之前就发送第二个请求,以降低通信延迟。
  • 支持响应分块。
  • 引入额外的缓存控制机制。
  • 引入内容协商机制,包括语言、编码、类型等。并允许客户端和服务器之间约定以最合适的内容进行交换。
  • 凭借 Host 标头,能够使不同域名配置在同一个 IP 地址的服务器上。

HTTP/1.x 的连接管理

连接管理是一个 HTTP 的关键话题:打开和保持连接在很大程度上影响着网站和 Web 应用程序的性能。在 HTTP/1.x 里有多种模型:短连接长连接和 HTTP 流水线

当面试官问我不同HTTP版本之间的差异

短连接

HTTP 最早期的模型和 HTTP/1.0 的默认模型,是短连接。每一个 HTTP 请求都由它自己独立的连接完成;这意味着发起每一个 HTTP 请求之前都会有一次 TCP 握手,而且是连续不断的。

这是 HTTP/1.0 的默认模型(如果没有指定 Connection 协议头,或者是值被设置为 close)。而在 HTTP/1.1 中,只有当 Connection 被设置为 close 时才会用到这个模型。

长连接

短连接有两个比较大的问题:

  • 创建新连接耗费的时间尤为明显
  • TCP 连接的性能只有在该连接被使用一段时间后(热连接)才能得到改善

一个长连接会保持一段时间,重复用于发送一系列请求,节省了新建 TCP 连接握手的时间,还可以利用 TCP 的性能增强能力。当然这个连接也不会一直保留着:连接在空闲一段时间后会被关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。

长连接也还是有缺点的;就算是在空闲状态,它还是会消耗服务器资源,而且在重负载时,还有可能遭受 DoS 攻击。这种场景下,可以使用非长连接,即尽快关闭那些空闲的连接,也能对性能有所提升。

流水线

HTTP 流水线在现代浏览器中并不是默认被启用的:

  1. 管道化要求服务端按照请求发送的顺序返回响应(FIFO),原因很简单,HTTP请求和响应并没有序号标识,无法将乱序的响应与请求关联起来。
  2. 客户端需要保持未收到响应的请求,当连接意外中断时,需要重新发送这部分请求。
  3. 只有幂等的请求才能进行管道化,也就是只有GET和HEAD请求才能管道化,否则可能会出现意料之外的结果

由于这些原因,流水线已被 HTTP/2 中更好的算法——多路复用(multiplexing)所取代。多路复用则很好的解决了长链接和管道化带来的队头阻塞问题。它允许在单一的 http2 连接上并行交错的传输请求和响应,而不需要顺序一一对应

前面提到HTTP管道化要求服务端必须按照请求发送的顺序返回响应,那如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达。

如果要实现真正的并行请求,只能通过建立多个持久连接,但是浏览器对于同一时间同一域名下的连接数有限制,一般是 4-8 个,Chrome 是 6 个。超过限制的数目会被阻塞。HTTP 允许客户端打开多条连接,并行地执行多个 HTTP 事务。

HTTP/2——为了更优异的表现

  • 多路复用:HTTP/2 允许同时发送多个请求和响应,而不是像 HTTP/1.1 一样只能一个一个地处理。这样可以减少延迟,提高效率,提高网络吞吐量。
  • 二进制传输:HTTP/2 使用二进制协议,与 HTTP/1.1 使用的文本协议不同。二进制协议可以更快地解析,更有效地传输数据,减少了传输过程中的开销和延迟。
  • 头部压缩:HTTP/2 使用 HPACK 算法对 HTTP 头部进行压缩,减少了头部传输的数据量,从而减少了网络延迟。
  • 服务器推送:HTTP/2 支持服务器推送,允许服务器在客户端请求之前推送资源,以提高性能。
  • 改进的安全性:HTTP/2 默认使用 TLS(Transport Layer Security)加密传输数据,提高了安全性。
  • 兼容 HTTP/1.1:HTTP/2 可以与 HTTP/1.1 共存,服务器可以同时支持 HTTP/1.1 和 HTTP/2。如果客户端不支持 HTTP/2,服务器可以回退到 HTTP/1.1。

多路复用

多路复用,复用的就是tcp连接。

多路复用代替原来的序列和阻塞机制,所有就是请求的都是通过一个 TCP 连接并发完成。同时也很好的解决了浏览器限制同一个域名下的请求数量的问题。

在 HTTP/2 中,有了二进制分帧之后,HTTP/2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2 中:

  • 同域名下所有通信都在单个连接上完成,同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应。
  • 单个连接可以承载任意数量的双向数据流,单个连接上可以并行交错的请求和响应,之间互不干扰。
  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。

HTTP/2 中数据传输的最小单位,因此帧不仅要细分表达 HTTP/1.x 中的各个部份,也优化了 HTTP/1.x 表达得不好的地方,同时还增加了 HTTP/1.x 表达不了的方式。

每一帧都包含几个字段,有length、type、flags、stream identifier、frame playload等,其中type 代表帧的类型,在 HTTP/2 的标准中定义了 10 种不同的类型,包括 HEADERS frame 和 DATA frame。此外还有: PRIORITY(设置流的优先级) RST_STREAM(终止流) SETTINGS(设置此连接的参数) PUSH_PROMISE(服务器推送) PING(测量 RTT) GOAWAY(终止连接) WINDOW_UPDATE(流量控制) CONTINUATION(继续传输头部数据)

在 HTTP 2.0 中,它把数据报的两大部分分成了 header frame 和 data frame。也就是头部帧和数据体帧。

流存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。 HTTP/2 长连接中的数据包是不按请求-响应顺序发送的,一个完整的请求或响应(称一个数据流 stream,每个数据流都有一个独一无二的编号)可能会分成非连续多次发送。它具有如下几个特点:

  • 双向性:同一个流内,可同时发送和接受数据
  • 有序性:流中被传输的数据就是二进制帧 。帧在流上的被发送与被接收都是按照顺序进行的
  • 并行性:流中的 二进制帧 都是被并行传输的,无需按顺序等待
  • 流的创建:流可以被客户端或服务器单方面建立, 使用或共享
  • 流的关闭:流也可以被任意一方关闭
  • HEADERS 帧在 DATA 帧前面
  • 流的 ID 都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数了

如何解决HTTP队头阻塞

对于HTTP1.1中管道化导致的请求/响应级别的队头阻塞,可以使用HTTP2解决。HTTP2不使用管道化的方式,而是引入了帧、消息和数据流等概念,每个请求/响应被称为消息,每个消息都被拆分成若干个帧进行传输,每个帧都分配一个序号。每个帧在传输是属于一个数据流,而一个连接上可以存在多个流,各个帧在流和连接上独立传输,到达之后再组装成消息,这样就避免了请求/响应阻塞。

当然,即使使用HTTP2,如果HTTP2底层使用的是TCP协议,仍可能出现TCP队头阻塞。

如何解决TCP队头阻塞

http2依旧基于TCP,所以依旧存在TCP队头阻塞的问题。

TCP中的队头阻塞的产生是由TCP自身的实现机制决定的,无法避免。想要在应用程序当中避免TCP队头阻塞带来的影响,只有舍弃TCP协议。

此外还有一个SCTP(流控制传输协议),它是和TCP、UDP在同一层次的传输协议。SCTP的多流特性也可以尽可能的避免队头阻塞的情况。

HTTP/3——基于 QUIC 的 HTTP

HTTP/3 有着与 HTTP 早期版本的相同语义,但在传输层部分使用 QUIC 而不是 TCP。所以不存在TCP队头阻塞的问题。

QUIC 旨在为 HTTP 连接设计更低的延迟。类似于 HTTP/2,它是一个多路复用协议,但是 HTTP/2 通过单个 TCP 连接运行,所以在 TCP 层处理的数据包丢失检测和重传可以阻止所有流。QUIC 通过 UDP 运行多个流,并为每个流独立实现数据包丢失检测和重传,因此如果发生错误,只有该数据包中包含数据的流才会被阻止。