【计算机网络】HTTP3、QUIC

24 阅读2分钟

HTTP/3

HTTP2的缺陷

  • TCP队头阻塞

  • TCP 与 TLS 的握手时延迟

    • TCP 三次握手和 TLS 四次握手(TLS 1.2)的过程需要 3 个 RTT 的时延
    • 拥塞控制「慢启动」过程,它会对 TCP 连接产生“减速”效果。
  • 网络迁移需要重新连接

    • IP 地址或者端口变动了,就会导致需要 TCP 与 TLS 重新握手

QUIC 协议

使用UDP:

  • 顺序、可靠性:数据包唯一标识

  • 无队头阻塞

    • 在同一条连接上并发传输多个 Stream,Stream 可以认为就是一条 HTTP 请求。
    • 当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。
  • 更快的连接建立

    • QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS 1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商,甚至在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。
  • 连接迁移

    • UDP 连接 ID 来标记通信的两个端点,网络IP 地址变化,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接

HTTP/3 协议

  • HTTP/3 同 HTTP/2 一样采用二进制帧的结构
  • 不同的地方在于 HTTP/2 的二进制帧里需要定义 Stream,而 HTTP/3 自身不需要再定义 Stream,直接使用 QUIC 里的 Stream,于是 HTTP/3 的帧的结构也变简单了。

  • Headers 帧(HTTP 头部)

    • 头部压缩算法升级成 QPACK,也采用了静态表、动态表及 Huffman 编码:

      • 静态表扩大到 91 项
      • Huffman 编码并没有多大不同
      • 动态表编解码方式不同
  • DATA 帧(HTTP 包体)属于数据帧。

动态表编解码改进

Why?

动态表时序性的,如果首次请求丢包,后续请求,无法解码HPACK 头部,后续的请求解码会阻塞到首次请求中丢失的数据包重传过来。

How?

QUIC 会有两个单向流的用法:

  • QPACK Encoder Stream:将一个字典(Key-Value)传递给对方,比如面对不属于静态表的 HTTP 请求头部,客户端可以通过这个 Stream 发送字典;
  • QPACK Decoder Stream:响应对方,告诉它刚发的字典已经更新到自己的本地动态表了,后续就可以使用这个字典来编码了。

用来同步双方的动态表,编码方收到解码方更新确认的通知后,才使用动态表编码 HTTP 头部。