HTTP协议学习记录(1/2/3)

134 阅读6分钟

HTTP

HTTP/1.1

  • 开启长连接,以支持连接重用
  • 分块传输编码,以支持流式响应
  • 请求管道,以支持并行请求处理
  • 改进缓存机制

长连接

握手成功后,能重用此连接,而不必每次请求都开启新连接

HTTP/1.0 需要手动添加 Connection: Keep-Alive

HTTP 管道

长连接可以让我们重用已有的连接,但多次请求必须满足 FIFO 队列的顺序:必须等待上一个请求的响应完成之后才能发送下一个请求。

管道则使 FIFO 队列从客户端迁移到服务端。客户端可以发送多个请求,而不必等待上一次完成。消除了发送请求的等待时间。服务端则按照 FIFO队列的顺序,一个一个地返回响应,但是服务端性能较强,还能并行处理多个任务,所以能大大提高效率。

队首阻塞

由于 HTTP/1.x 不允许同一个连接上的数据交错到达(多路复用),服务端只能按照请求顺序,等上一个响应处理完成才能发送下一个响应,即便第二个响应可能先于第一个响应处理完。甚至假如第一个请求的响应无限挂起,后续所有的响应都将被阻塞。

处理完成但并没有发送的响应资源会被放入缓冲区,占用了服务器资源,以此可能会形成服务端的一个受攻击面。

如果一个响应失败,会让整个TCP连接失效,缓冲区还未发送的响应资源也都浪费了

使用多个 TCP 连接

建立多个 TCP 连接,达到多个请求并行发送。

  • TCP 流会竞争带宽,无法应对优先级问题
  • 占用大量连接资源
  • 处理多个请求,复杂度更高
  • TCP 的慢启动,传输比较小的文件时效率低下

网络性能优化

  • 减少 DNS 查询
  • 减少 HTTP 请求
    • 资源打包、精灵图、base64。但是首屏时间长因为必须等所有资源都加载完才会执行
  • 使用 CDN —— 减少 TCP 连接的网络延迟
  • 配置缓存
  • Gzip 压缩
  • 避免 HTTP 重定向 —— 重定向极其耗时,还会导致额外的 DNS 查询,TCP 连接

HTTP/2

  • HTTP/2 更快、更简单、更稳定,将针对 HTTP/1.1 所做的一些优化操作内置在了传输层中。
  • HTTP/2 的主要目标是通过支持请求与响应的多路复用,以减小延迟。并通过首部压缩降低开销,同时增加对请求优先级和服务端推送的支持。
  • HTTP/2 修改了数据格式化(分帧)以及数据传输方式,但没有改变 HTTP 的语义。因为其将复杂操作放入了分帧层,于是老版本的应用也可以不必修改而在 HTTP/2 下运行。

二进制分帧层

在HTTP层下方,定义了如何封装HTTP消息并在客户端与服务器之间传输。

HTTP/1.x 协议以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息和帧,并采用二进制格式将其编码。

分为 Headers帧、DATA帧

数据流、消息、帧

数据流:已建立的连接内的双向字节流,可以承载一条或多条消息

消息:与请求、响应所对应的完整的一系列的帧

帧:HTTP/2 通信的最小单位,每个帧都包含帧头,并至少会标识所属数据流,流ID奇数为客户端发起的,偶数则为服务端发起的

  • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流
  • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息
  • 每条消息都是一条 HTTP 消息,包含一个或多个帧
  • 帧是最小的通信单位,承载着特定类型的数据。来自不同的数据流的帧可以交错发送,再根据帧头的数据流标识符重新组装

多路复用

在 HTTP/1.x 中,如果客户端向发起多个并行请求以提升性能,则必须使用多个 TCP 连接,但每个连接每次只能交付一个响应,多个响应必须要排队,造成队首阻塞。

在 HTTP/2 中,客户端和服务端可以把 HTTP 消息分解为互不干扰的帧,然后乱序发送,在另一端重新组合。

  • 每个响应之间都互不干扰地并行交错地发送
  • 每个请求之间都互不干扰地并行交错地发送
  • 一个连接即可并行发送多个请求、响应
  • 消除不必要的延迟(请求等待、响应等待)

请求优先级

每个流都可以携带一个 31bit 的优先值:0代表最高,2^31-1代表最低。 服务端根据流的优先级,控制资源分配,并在响应数据准备好之后,优先发送高优先级的帧

流量控制

待续

服务端推送

服务端可以额外地向客户端推送资源,而不必等待客户端发起请求。一般作用于必要的资源。

所有服务端推送的数据流都由 PUSH_PROMISE 帧发起,并先于客户端发送请求,因为如果服务端推送的资源恰好之后客户端要请求,则会造成浪费

首部压缩

在 HTTP/1.x 中,首部都是以纯文本的格式发送的,占用空间大。

HPACK

  1. 通过哈弗曼编码来对首部进行编码,从而减小传输大小

  2. 使用首部表来跟踪和存储之前发送的键值对,相同的数据不用发送,不同的数据要么替换表中相关的数据要么拼接在表中相关的数据之后。

    1. HPACK 压缩上下文包含一个静态表和一个动态表
    2. 静态表提供了一些常用 HTTP 首部,如果首部有静态表的数据且为新数据,则修改静态表
    3. 动态表最初为空,根据连接交换的值而更新,如果首部有静态表没有的数据切位新数据,则修改动态表

HTTP/2 的缺陷

主要来源于 TCP 的缺陷

TCP 队首阻塞

如果某个包丢失,则会触发 TCP 重传机制,整个 TCP 连接都会被阻塞,等待乱序包重传。

在 HTTP/1.1 中,一般使用多条 TCP 连接,如果一条阻塞,其他不受影响;但是 HTTP/2 使用单个 TCP 连接,如果某条数据流的帧丢失,则会阻塞所有流。据统计,如果丢包率大于 2%,HTTP/2 的传输效率反而低于 HTTP/1.x。

TCP 握手延迟

TCP 握手及其引起的 TLS 握手有较大延迟,会影响用户体验

HTTP/3

基于 UDP

QUIC

  • 以 UDP 为基础,并自己实现了可靠机制、流量控制、拥塞控制
  • 继承了 TLS 加密功能
  • 实现多路复用,并且能在同一物理连接上存有多个独立的数据流,解决了 TCP 队首阻塞
  • 实现了快速握手

缺陷

由于 UDP 使用不如 TCP 广泛,获得的优化不多,于是在中间网络设备运输时丢包率较高