QUIC协议 - 6 - QUIC的拥塞控制机制
QUIC协议本身(RFC 9002)并没有强制规定必须使用哪一种拥塞控制。它只定义了拥塞控制器与QUIC协议栈交互的接口和信号:
QUIC最流行的两种拥塞控制算法是CUBIC和BBR。
RFC 中没有以特定编程语言的 API 形式来定义接口,但它描述了一套逻辑上的接口。可以其分为以下两类 conceptual API:
输入接口 (协议栈 -> 拥塞控制器)
这些是协议栈向拥塞控制器提供数据和事件的接口:
- OnPacketSent(packet):- 何时调用: 每当一个数据包被发送时。
- 传递信息: 数据包大小 (bytes_sent)、包号、是否需要确认 (is_ack_eliciting) 等。
- 作用: 让控制器更新在途数据量 (bytes_in_flight)。
 
- OnAckReceived(acked_packets):- 何时调用: 当收到一个 ACK 帧时。
- 传递信息: 一个列表,包含了所有被确认的数据包的详细信息(包号、发送时间、数据包大小等),以及最新的 RTT 测量值。
- 作用: 这是最主要的良性反馈信号,用于增加拥塞窗口,更新 RTT 估计。
 
- OnPacketsLost(lost_packets):- 何时调用: 当丢包检测器宣告有数据包丢失时。
- 传递信息: 丢失的数据包列表。
- 作用: 这是最主要的拥塞信号,用于触发拥塞窗口减小等拥塞响应。
 
- OnCongestionEvent(ecn_counts):- 何时调用: 当收到带有 ECN (显式拥塞通知) 标记的 ACK 时。
- 作用: 提供了一个在丢包发生前的早期拥塞信号。
 
输出接口 (拥塞控制器 -> 协议栈)
这些是协议栈向拥塞控制器获取决策的接口:
- GetCongestionWindow() -> bytes:- 作用: 协议栈通过此接口查询当前拥塞窗口 (cwnd) 的大小。这是决定能否发送新数据的核心依据。
 
- 作用: 协议栈通过此接口查询当前拥塞窗口 (
- GetPacingRate() -> bytes_per_second(可选但推荐):- 作用: 对于 BBR 等基于速率的算法,控制器可以直接提供一个建议的发送速率。协议栈应以此速率平滑地发送数据(Pacing),而不是瞬间把 cwnd用完,以避免在网络中产生流量尖峰。
 
- 作用: 对于 BBR 等基于速率的算法,控制器可以直接提供一个建议的发送速率。协议栈应以此速率平滑地发送数据(Pacing),而不是瞬间把 
- GetProbeTimeout() -> duration:- 作用: 查询 PTO (探测超时) 的时长,用于设置丢包检测计时器。