QUIC 原理

179 阅读5分钟

参考文章: quic-是如何实现可靠传输的

QUIC 是如何实现可靠传输的?

image.png

Packet Header

image.png

Packet Header 两种:

  • Long Packet Header 用于首次建立连接。
  • Short Packet Header 用于日常传输数据。

重点:

  • QUIC 三次握手建立连接,协商连接ID
  • 日常传输数据的 Short Packet Header 只需要传输 Destination Connection ID
  • Short Packet Header 的 Packet Number 是每个报文独一无二的编号,严格递增。

Packet N丢失,重传的 Packet N 的 Packet Nunmber 可能就是 N+M。

Packet Number 单调递增:

  • 精确计算RTT,没有TCP重传的歧义性问题
  • 乱序确认

QUIC Frame Header

一个 Packet 报文中可以存放多个 QUIC Frame。 image.png

Frame 类似于 HTTP2 的设计。多种类型,功能不同,格式不同。

Stream Frame

  • StreamID: 区分多个并发传输的消息。
  • Offset:类似于 TCP 协议中 Seq 序号,保证数据的顺序性和可靠性
  • Length: Frame长度。
  • data: 负载数据。

Frame Header 中 Packet Nunber 严格递增。丢失Packet N 和重传 Packet N+M 通过 Stream ID + Offset 确认一致,是否是相同数据包。

总的来说,QUIC通过单向递增的PacketNumber,配合StreamID与Offset字段信息,可以支持乱序确认而不影响数据包的正确组装,摆脱了TCP必须按顺序确认应答ACK的限制,解决了TCP因某个数据包重传而阻塞后续所有待发送数据包的问题

QUIC 是如何解决 TCP 队头阻塞问题的?

TCP 队头阻塞 ---> 接收窗口的队头阻塞问题:接收方收到的数据范围必须在接收窗口范围内,如果收到超过接收窗口范围的数据,就会丢弃该数据。

导致接收窗口的对头阻塞的原因:因为 TCP 必须按序处理数据,只有在处理完有序的数据后,滑动窗口才能往前滑动,否则阻塞。

HTTP/2 的队头阻塞

HTTP/2 Stream实现HTTP并发传输,每一个Stream代表HTTP/1.1的请求响应。
不同Stream的帧可以乱序发送(可以并发不同的Stream),接收方通过每个帧头部的Stream ID有序组装成HTTP消息,而同一Stream内部的帧必须严格有序。
问题是:HTTP/2多个Stream请求在同一条TCP连接传输,意味着共用同一个TCP滑动窗口,那么当数据丢失,发生队头阻塞。

没有队头阻塞的 QUIC

QUIC 同样有 Stream,一条 QUIC 可以并发发送多个 HTTP请求(Sream)。
QUIC给每一个Stream分配一个独立的滑动窗口,使得一个连接上多个Stream之间没有依赖关系。

QUIC 是如何做流量控制的?

TCP 流量控制:接收方 告知 发送方,接收方 接收窗口的大小,发送方 可以控制发送的数据量。

QUIC 流量控制:

  • window_update帧:告知对端自己可以接收的字节数,发送方不会超过。
  • BlockFrame帧:告知对端由于流量控制被阻塞,无法发送数据。

QUIC里同一个Stream的数据要保证顺序,为实现可靠传输。

QUIC两种流量控制:

  • Stream:Stream可以认为是一条HTTP,每个Stream都有独立的滑动窗口。
  • Connection:限制连接中所有Stream想加起来的总字节数,防止发送方超过链接的缓冲容量。

Stream 级别的流量控制

初始状态: image.png

如下图,接收方收到发送方发送的数据。存在多种情况:

  • 已被上层读取数据包
  • 未被上层读取数据包
  • 丢失数据包
  • 已收到但乱序的数据包

接收窗口的左边界取决于接收到的最大偏移字节数。此时:接收窗口 = 最大窗口数 - 接收到的最大偏移量。

  • TCP 的接收窗口,当前面还有字节未接收但收到了后面的字节,依旧阻塞。
  • QUIC的接收窗口,左边界滑动条件取决于接收到的最大偏移字节数。 image.png

如下图,当图中绿色部分数据超过最大接收窗口的一半后,最大接收窗口向右移动,接收窗口的右边界也向右扩展,同时给发送端发送 窗口更新帧,当发送方收到接收方的窗口更新帧后,发送窗口的右边界也会往右扩展。 绿色部分,是收到的顺序的数据,如果中途丢包,导致绿色部分的数据没有超过最大接收窗口的一半,那么接收窗口阻塞。只影响同一个stream。 image.png

Connection 流量控制

此时,其接收窗口是各个Stream接收窗口大小之和。 image.png

QUIC 对拥塞控制改进

QUIC协议当前默认使用了TCP的Cubic拥塞控制算法(我们熟知的慢开始、拥塞避免、快重传、快恢复策 略),同时也支持CubicBytes、Reno、RenoBytes、BBR、PCC等拥塞控制算法,相当于将TCP的拥塞控制算 法照搬过来了。

QUIC 更快的连接建立

HTTP/1 和 HTTP/2,TCP和TLS分层,需要先TCP握手,再TLS握手,需要3RTT延迟。如果Session会话复用,也要至少2个RTT。

QUIC内部包含TLS 1.3,在帧里携带TLS“记录”。只需要1个RTT即可同时完成建立连接与密钥协商,在第二次连接的时候,应用数据包可以和QUIC握手信息(链接信息+TLS信息)一起发送,达到 0-RTT。 image.png

QUIC 是如何迁移连接的?

基于TCP的HTTP协议,由于通过四元组(源ID,源端口,目的IP,目的端口)确定一条TCP连接。

QUIC 通过ID来标记连接的两个端点,客户端、服务器可以各自选择一组ID来标记自己。当移动设备网络发送变化,导致IP地址变化,只要仍保留上下文信息(比如连接ID,TLS密钥等),就可以继续复用原链接,消除重连的成本。