# 拥塞控制总览 · GoogCC 与该发多快

> 该发多快？发太快网络堵、太慢浪费。WebRTC 的答案是 GoogCC——一个跑在发送端的拥塞控制器。这一章讲清它的双控制器结构（延迟based + 丢包based 取小）、以 Transport-CC 反馈为输入、产出目标码率的闭环，以及 GoogCcNetworkController 这个总成。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/congestion-control-overview
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 拥塞控制总览 · GoogCC 与该发多快

[第 4 部分](https://daiw.org/manual/webrtc/transport-cc)反复逼近一个问题：**到底该发多快？** 这是实时通信最难、也最能拉开体验差距的部分——估准了，烂网也能流畅；估错了，好网也卡成 PPT。WebRTC 的答案是一套叫 **GoogCC（Google Congestion Control）** 的算法，在 `modules/congestion_controller/goog_cc/`。第 5 部分就拆解它。

## 目标：贴着网络容量发

拥塞控制要解的，是一个动态平衡：

<Callout type="info">
  **发送速率要**尽可能贴着网络的实时可用带宽**——既不超过（超了就[排队、延迟、丢包](https://daiw.org/manual/webrtc/transport-cc)），也别太保守（浪费带宽，画质白白打折）。** 难点在于，网络可用带宽**看不见、且时刻在变**：别人在下载、Wi-Fi 信号波动、路由拥塞……你只能靠[反馈信号](https://daiw.org/manual/webrtc/transport-cc)去**估计**它，并**持续追踪**它的变化。这就是「带宽估计（Bandwidth Estimation，BWE）」——拥塞控制的核心。估出来的带宽，变成**目标码率**，交给[编码器](https://daiw.org/manual/webrtc/source-map)据此调整画质 / 帧率。整个系统是一个**闭环**：发包 → [收反馈](https://daiw.org/manual/webrtc/transport-cc) → 估带宽 → 定码率 → 编码器调整 → 再发包。
</Callout>

## 两个信号，两个控制器

GoogCC 用**两种信号**判断拥塞，对应**两个控制器**——这是它的核心结构：

<Callout type="info">
  **GoogCC 同时跑「延迟based」和「丢包based」两个带宽估计，取两者的较小值。**

  - **延迟based(delay-based)** —— 看[包的延迟趋势](https://daiw.org/manual/webrtc/delay-based-bwe)。延迟**在涨**，说明网络缓冲区在排队、拥塞将至——**在丢包之前就预警**。这是**主控制器**，反应快、灵敏。
  - **丢包based(loss-based)** —— 看[丢包率](https://daiw.org/manual/webrtc/loss-based-bwe)。丢包多，说明已经发过量了。它更**滞后**（丢包是拥塞的结果而非先兆），但更**确凿**，作为兜底。

  **取小**：两个估计谁更保守听谁的——延迟说“该降”就降，哪怕还没丢包。为什么要两个？因为单靠丢包**太迟**（等丢包就晚了），单靠延迟在某些网络（如有主动丢包的链路）**不够**。两者结合，既能[提前反应](https://daiw.org/manual/webrtc/delay-based-bwe)，又有[丢包兜底](https://daiw.org/manual/webrtc/loss-based-bwe)。这是 GoogCC 相比早期「只看丢包」算法的关键进步。
</Callout>

## 总成：GoogCcNetworkController

把这些拼在一起的，是 **`GoogCcNetworkController`**（`modules/congestion_controller/goog_cc/goog_cc_network_control.h`），它实现 `NetworkControllerInterface`。看它持有的成员，整个第 5 部分的地图就出来了：

```cpp
// goog_cc_network_control.h(节选成员)
std::unique_ptr<DelayBasedBwe> delay_based_bwe_;                    // 延迟based 估计
// LossBasedBweV2                                                   // 丢包based 估计
const std::unique_ptr<ProbeController> probe_controller_;          // 主动探测
congestion_window_pushback_controller_;                            // 拥塞窗口
// acknowledged_bitrate_estimator                                   // 实际吞吐估计
NetworkControlUpdate OnTransportPacketsFeedback(...);              // 吃反馈,吐决策
```

| 成员 | 干什么 | 本教程 |
| --- | --- | --- |
| `DelayBasedBwe` | [延迟趋势](https://daiw.org/manual/webrtc/delay-based-bwe)估带宽（含 trendline + over-use） | [下一章](https://daiw.org/manual/webrtc/delay-based-bwe) |
| `LossBasedBweV2` | [丢包](https://daiw.org/manual/webrtc/loss-based-bwe)估带宽 | 第 5 部分 |
| `ProbeController` | [主动发探测包](https://daiw.org/manual/webrtc/probing)试探更高带宽 | 第 5 部分 |
| `CongestionWindow...` | [限制在途数据量](https://daiw.org/manual/webrtc/congestion-window) | 第 5 部分 |
| acknowledged bitrate | 估**实际到达**的吞吐 | 第 5 部分 |

核心入口是 **`OnTransportPacketsFeedback`**——它吃 [Transport-CC 反馈](https://daiw.org/manual/webrtc/transport-cc)（每个包何时到的），吐出 `NetworkControlUpdate`（新的目标码率、pacing 速率等决策）。**一次反馈进来，一轮估计与决策产出**，闭环就此转动。

## 在哪运行

呼应[反馈那章](https://daiw.org/manual/webrtc/transport-cc)：GoogCC 跑在**发送端**（它信息最全——同时知道发送时间和反馈来的到达时间）。它是[可替换的](https://daiw.org/manual/webrtc/factory-and-context)——`PeerConnectionFactoryDependencies` 的 `network_controller_factory` 就是[换拥塞控制算法的口子](https://daiw.org/manual/webrtc/factory-and-context)。GoogCC 是默认实现，但你能塞自己的。它归 [`RtpTransportControllerSend`](https://daiw.org/manual/webrtc/source-map)（[第 9 部分](https://daiw.org/manual/webrtc/source-map)）调度。

## 小结与下一章

**GoogCC**（`modules/congestion_controller/goog_cc/`）是 WebRTC 的拥塞控制，目标是让发送速率**贴着看不见、时刻变的网络带宽**。它用**两个信号**：**延迟based**（主控，看[延迟趋势](https://daiw.org/manual/webrtc/delay-based-bwe)，丢包前预警）+ **丢包based**（兜底，看[丢包](https://daiw.org/manual/webrtc/loss-based-bwe)），**取较小值**。总成 **`GoogCcNetworkController`** 持有 [DelayBasedBwe](https://daiw.org/manual/webrtc/delay-based-bwe)、LossBasedBweV2、[ProbeController](https://daiw.org/manual/webrtc/probing)、[拥塞窗口](https://daiw.org/manual/webrtc/congestion-window)等，核心入口 `OnTransportPacketsFeedback`（[吃反馈吐决策](https://daiw.org/manual/webrtc/transport-cc)）。跑在发送端，[可替换](https://daiw.org/manual/webrtc/factory-and-context)。

主控制器是延迟based——它怎么从一堆包的到达时间里，看出「延迟在涨、拥塞将至」？下一章深入 trendline 与 over-use detector。👉 [延迟based 带宽估计](https://daiw.org/manual/webrtc/delay-based-bwe)。

## 参考资料

- [1] libwebrtc 源码.`modules/congestion_controller/goog_cc/goog_cc_network_control.h` / `.cc`（`GoogCcNetworkController`、`OnTransportPacketsFeedback`）。
- [2] libwebrtc 源码.`api/transport/network_control.h`（`NetworkControllerInterface`）。
- [3] Holmer et al.「A Google Congestion Control Algorithm for Real-Time Communication」（IETF draft）。
