在 TCP连接管理 中,看到了 TCP 如何通过三次握手建立连接、四次挥手释放连接,以及 TIME_WAIT、SYN Flood 等连接层面的工程问题。连接建立只是起点——真正的问题在于:连接建立之后,数据该怎么传?
发太快,接收方处理不过来,数据丢失;发太快,路由器队列溢出,网络崩溃;发太慢,带宽浪费,延迟增加。TCP 需要一套精巧的”交通管制”系统:流控(flow control)保护接收方不被淹没,拥塞控制(congestion control)保护网络不被压垮。两者协同工作,决定了 TCP 连接上数据传输的速率与节奏。
本章从 1986 年的互联网拥塞崩溃事件出发,先看滑动窗口机制如何实现流控,再深入慢启动、拥塞避免、快速重传与快速恢复的完整算法,最后追踪从 Reno 到 Cubic 再到 BBR 的演进脉络,理解拥塞控制如何从”丢包驱动”走向”模型驱动”。这些知识不仅是理解 TCP 性能的关键,也是理解 QUIC与HTTP/3 为何要重新设计传输层的基础——QUIC 的拥塞控制正是站在 TCP 的肩膀上,解决了 TCP 难以逾越的架构限制。
一、为什么需要流控和拥塞控制
1.1 两种不同的”太快”
TCP 发送方面临两个独立的速率约束:
- 接收方约束:接收方的处理速度有限,缓冲区有限。如果发送方发送速率超过接收方的处理能力,数据会被丢弃。这是流控要解决的问题。
- 网络约束:网络中间的路由器缓冲区有限。如果所有发送方的总速率超过链路带宽,路由器队列溢出,数据包被丢弃。这是拥塞控制要解决的问题。
两者看似相似——都是”发太快导致丢包”——但本质不同:流控是端到端的问题,只需要发送方和接收方协调;拥塞控制是全局问题,需要所有发送方共同协作,而网络中间设备不会直接告诉发送方”我拥塞了”。
1.2 1986 年的拥塞崩溃
1986 年 10 月,互联网发生了第一次有记录的拥塞崩溃(congestion collapse)。从 Lawrence Berkeley Laboratory 到 UC Berkeley 的吞吐量从正常的 32 Kbps 暴跌到 40 bps——下降了近 1000 倍。
原因令人深思:当路由器开始丢包时,TCP 发送方会超时重传。但当时的 TCP 没有拥塞控制机制——重传的数据包与原始数据包竞争同一拥塞链路,导致更多丢包、更多重传,形成恶性循环。网络中充斥着重传数据包,有效吞吐量趋近于零。
拥塞崩溃的核心特征是:网络负载增加,但有效吞吐量反而下降。这不是简单的”变慢”,而是系统进入了一个正反馈的恶化循环——越拥塞越重传,越重传越拥塞。
这次事件直接催生了 Van Jacobson 在 1988 年提出的 TCP 拥塞控制算法(即 TCP Tahoe),奠定了现代拥塞控制的基础。
1.3 流控与拥塞控制的分工
| 维度 | 流控(Flow Control) | 拥塞控制(Congestion Control) |
|---|---|---|
| 保护对象 | 接收方 | 网络中间设备 |
| 信息来源 | 接收方显式通告(rwnd) | 发送方隐式推断(丢包、延迟) |
| 作用范围 | 单条连接 | 所有共享路径的连接 |
| 窗口变量 | rwnd(接收窗口) | cwnd(拥塞窗口) |
| 生效窗口 | min(rwnd, cwnd) | min(rwnd, cwnd) |
发送方实际使用的发送窗口是 rwnd 和 cwnd 中的较小值:发送窗口 = min(rwnd, cwnd)。流控说”接收方还能接收多少”,拥塞控制说”网络还能承受多少”,取两者中更保守的限制。
二、滑动窗口与流控
2.1 接收窗口的工作原理
TCP 使用滑动窗口(sliding window)机制实现流控。接收方在每次 ACK 中携带接收窗口(rwnd)字段,告诉发送方”我还有多少缓冲区可用”。
滑动窗口的核心逻辑:
- 发送方收到 ACK 后,窗口左沿右移(已确认的数据释放)
- 接收方应用读取数据后,rwnd 增大,窗口右沿右移
- 发送方发送数据后,可用窗口缩小
- 发送方不能发送超过 min(rwnd, cwnd) 的数据
2.2 零窗口探测
当接收方缓冲区满时,rwnd = 0,发送方必须停止发送。但接收方缓冲区释放后如何通知发送方?TCP 设计了零窗口探测(Zero Window Probe)机制:
# Linux 零窗口探测相关参数sysctl net.ipv4.tcp_keepalive_time # 7200s,保活探测间隔sysctl net.ipv4.tcp_keepalive_intvl # 75s,探测间隔sysctl net.ipv4.tcp_keepalive_probes # 9,探测次数
# 零窗口探测专用参数sysctl net.ipv4.tcp_retries2 # 15,数据重传最大次数发送方在收到 rwnd = 0 的 ACK 后,启动持续计时器(persist timer)。计时器超时后,发送方发送一个 1 字节的探测数据段,触发接收方重新通告窗口。如果 rwnd 仍为 0,重新启动计时器,且计时器指数退避。
2.3 糊涂窗口综合征
糊涂窗口综合征(Silly Window Syndrome, SWS)是流控中一个经典的效率问题:当接收方缓冲区快满时,应用每次只读取少量数据,导致 rwnd 只有一小段可用空间;发送方立即发送小数据段填充这段空间,结果网络中充斥着低效的小包。
解决方案是双端的:
- 接收方:不立即通告小窗口,等到窗口达到合理大小(MSS 或缓冲区一半)再通告(Clark 方案)
- 发送方:不立即发送小数据段,等到积累足够数据再发送(Nagle 算法)
# Nagle 算法默认开启,可关闭(低延迟场景如游戏、SSH)sysctl net.ipv4.tcp_nodelay # 0=开启Nagle, 1=关闭
# 延迟 ACK(与 Nagle 交互可能产生额外延迟)sysctl net.ipv4.tcp_delack_min # 40ms,延迟ACK最小超时sysctl net.ipv4.tcp_ato_min # 200ms,延迟ACK自适应最小值Nagle 算法和延迟 ACK 同时开启时可能产生”死锁”:发送方等更多数据才发(Nagle),接收方等数据才回 ACK(延迟 ACK),双方都在等对方。这是 TCP 编程中经典的延迟陷阱,交互式应用应关闭 Nagle(设置 TCP_NODELAY)。
三、慢启动与拥塞避免
3.1 拥塞窗口的增长曲线
TCP 拥塞控制的核心状态变量是拥塞窗口(cwnd),它决定了发送方在未收到 ACK 之前能向网络注入多少数据。cwnd 的增长分为两个阶段:
- 慢启动(Slow Start):cwnd 从 1 MSS 开始,每收到一个 ACK,cwnd 增加 1 MSS。一个 RTT 内所有段被确认后,cwnd 翻倍——指数增长。名称”慢启动”是相对于”一开始就发送整个窗口”而言,并非增长速度慢。
- 拥塞避免(Congestion Avoidance):当 cwnd 达到慢启动阈值(ssthresh)后,切换为线性增长——每个 RTT cwnd 增加 1 MSS。
慢启动的”慢”是历史命名,容易产生误解。实际上慢启动阶段 cwnd 指数增长,速度远快于拥塞避免的线性增长。真正的”慢”是相对于”无控制地一次性发送全部数据”而言——TCP 选择从 1 MSS 开始逐步探测,而非冒进地占满带宽。
3.2 ssthresh 的作用
ssthresh 是慢启动和拥塞避免的分界线:
| 事件 | cwnd 变化 | ssthresh 变化 |
|---|---|---|
| 连接建立 | cwnd = initcwnd(默认 10 MSS) | ssthresh = ∞ |
| cwnd < ssthresh | 慢启动(指数增长) | 不变 |
| cwnd ≥ ssthresh | 拥塞避免(线性增长) | 不变 |
| 超时丢包 | cwnd = 1 MSS | ssthresh = cwnd / 2 |
| 3 次重复 ACK | cwnd = ssthresh + 3 MSS | ssthresh = cwnd / 2 |
# Linux 拥塞控制相关参数sysctl net.ipv4.tcp_init_cwnd # 初始拥塞窗口(默认10)sysctl net.ipv4.tcp_no_metrics_save # 0=缓存上次cwnd, 1=不缓存
# 查看当前连接的 cwnd 和 ssthreshss -ti dst 10.0.0.1# 输出示例:# cubic cwnd:32 ssthresh:24 send 45.2Mbps ...3.3 初始拥塞窗口的演进
初始拥塞窗口(initcwnd)的值经历了重要变化:
- RFC 2581(1999):initcwnd = 1 MSS
- RFC 3390(2002):initcwnd = min(4 MSS, 4380 字节)
- RFC 6928(2013):initcwnd = 10 MSS
从 1 MSS 到 10 MSS 的提升,反映了对现代网络的认知:当今互联网的带宽延迟积远大于早期,1 MSS 的初始窗口导致短连接在慢启动阶段就结束了,永远无法充分利用带宽。
四、快速重传与快速恢复
4.1 三个重复 ACK 的含义
超时重传的代价很大——RTO 通常在数百毫秒到秒级,期间连接完全空闲。TCP 设计了快速重传(Fast Retransmit)机制,用重复 ACK 来检测丢包,避免等待超时。
当接收方收到乱序数据段时,会立即发送对最后一个按序字节的 ACK。如果段 3 丢失,段 4、5、6 到达时接收方都会发送对段 2 的 ACK——产生三个重复 ACK。发送方收到三个重复 ACK 后,立即重传丢失的段,无需等待超时。
4.2 快速恢复算法
快速重传之后,发送方进入快速恢复(Fast Recovery)阶段,而非回到慢启动:
- 设置 ssthresh = cwnd / 2
- 设置 cwnd = ssthresh + 3 MSS(3 MSS 对应 3 个重复 ACK 已离开网络)
- 每收到一个重复 ACK,cwnd 增加 1 MSS(允许发送新数据)
- 收到新数据的 ACK 时,cwnd = ssthresh,进入拥塞避免
快速恢复的核心思想:三个重复 ACK 说明网络仍在传递数据(只是丢了一个包),所以不需要像超时那样激进地降低发送速率。
4.3 Reno 与 NewReno 的区别
| 特性 | TCP Reno | TCP NewReno |
|---|---|---|
| 快速恢复退出条件 | 收到首个新 ACK | 收到确认所有未确认数据的 ACK |
| 单窗口多丢包 | 只能恢复一个丢包,其余等超时 | 可在一次快速恢复中恢复多个丢包 |
| 部分 ACK 处理 | 视为新 ACK,退出快速恢复 | 视为重复 ACK,继续快速恢复 |
| 典型场景 | 单个丢包恢复效率高 | 多个丢包恢复效率显著提升 |
NewReno 的改进看似微小,但在高延迟、高丢包率网络中效果显著。考虑一个窗口内丢失两个数据段的情况:Reno 只能恢复第一个,第二个必须等超时重传;NewReno 可以在一次快速恢复中依次恢复两个丢包,避免数百毫秒的等待。
# Linux 默认使用 NewReno 的改进版(内置于各拥塞控制算法)sysctl net.ipv4.tcp_recovery # 快速恢复模式
# 查看当前拥塞控制算法sysctl net.ipv4.tcp_congestion_control# 输出:tcp_congestion_control = cubic五、Cubic与BBR
5.1 Cubic:丢包驱动的巅峰
Cubic 是 Linux 内核 2.6.19 以来的默认拥塞控制算法,也是目前互联网上部署最广泛的算法。它的核心改进是让 cwnd 的增长与 RTT 无关——之前的算法(如 Reno、BIC)在长 RTT 链路上增长过慢。
Cubic 的窗口增长函数:
其中:
- (默认 Cubic 参数)
- 是上次丢包时的 cwnd
- 是窗口增长到 所需的时间
- 是距上次丢包的时间
Cubic 的增长曲线呈三次函数形状:丢包后先快速增长(凹函数阶段),接近 时减速(凸函数阶段),超过 后缓慢探索(凹函数阶段),直到再次丢包。
# Cubic 参数调整sysctl net.ipv4.tcp_cubic_beta # 0.7,乘法减少因子sysctl net.ipv4.tcp_cubic_fast_converge # 1,快速收敛开关
# 切换到 Cubic 算法sysctl -w net.ipv4.tcp_congestion_control=cubic5.2 BBR:模型驱动的革命
BBR(Bottleneck Bandwidth and Round-trip propagation time)由 Google 的 Neal Cardwell 等人在 2016 年提出,彻底改变了拥塞控制的范式:不再以丢包作为拥塞信号,而是通过显式建模网络的瓶颈带宽和最小 RTT 来控制发送速率。
BBR 的两个核心参数:
- BtlBw(Bottleneck Bandwidth):路径瓶颈带宽,通过测量交付速率的最大值估计
- RTprop(Round-trip propagation time):路径最小 RTT,通过测量 RTT 的最小值估计
BBR 的发送速率由这两个参数决定:发送速率 = BtlBw,在途数据量 = BtlBw × RTprop(即带宽延迟积 BDP)。
BBR 的四个状态:
- Startup:类似慢启动,以 2x 速率增长,直到交付速率不再增长(发现 BtlBw)
- Drain:排空 Startup 阶段积累的队列,将发送速率降至 BtlBw
- ProbeBW:稳态阶段,以 BtlBw 发送,周期性地以 1.25x 速率探测更高带宽
- ProbeRTT:定期降低发送速率(4 个 MSS),探测更小的 RTprop
5.3 Cubic 与 BBR 的对比
| 维度 | Cubic | BBR |
|---|---|---|
| 拥塞信号 | 丢包 | 带宽和 RTT 模型 |
| 增长函数 | W(t) = C(t-K)³ + Wmax | 基于模型计算发送速率 |
| 缓冲区占用 | 尽量填满瓶颈缓冲区 | 尽量不产生队列 |
| 有损网络表现 | 丢包即减窗,吞吐量骤降 | 丢包不减窗,吞吐量稳定 |
| 高带宽长肥网络 | 增长缓慢,难以利用带宽 | 快速探测瓶颈带宽 |
| 公平性 | 与 Reno/Cubic 公平共存 | 可能抢占 Cubic 带宽 |
| RTT 公平性 | 长 RTT 增长更慢 | 与 RTT 无关 |
| Linux 默认 | 2.6.19 起 | 需手动启用 |
| 适用场景 | 一般互联网 | 高带宽、有损链路(如无线) |
# 启用 BBR(需要内核 4.9+)echo "bbr" | sudo tee /etc/sysctl.d/99-bbr.confsysctl -p /etc/sysctl.d/99-bbr.conf
# 验证 BBR 已启用sysctl net.ipv4.tcp_congestion_controlsysctl net.ipv4.tcp_available_congestion_control# 输出应包含 bbr
# 查看当前连接使用的拥塞控制算法ss -ti | grep -E "cubic|bbr"六、拥塞控制的现实影响
6.1 慢启动对短流的影响
互联网上大多数 TCP 连接是短流——一个网页请求可能只有几十 KB 数据。慢启动的指数增长意味着短流往往在慢启动阶段就结束了,永远无法达到可用带宽。
假设路径带宽 100 Mbps、RTT 50ms、MSS 1460 字节:
- 带宽延迟积 BDP = 100 Mbps × 50ms = 625 KB ≈ 428 MSS
- 从 initcwnd = 10 MSS 开始,需要约 6 个 RTT 才能超过 BDP
- 6 个 RTT = 300ms,在此期间传输的数据量约 10+20+40+80+160+320 = 630 MSS ≈ 920 KB
对于 100 KB 以下的短流,慢启动阶段就结束了,带宽利用率极低。这正是 QUIC与HTTP/3 引入 0-RTT 技术的动机之一——复用之前连接的拥塞信息,跳过慢启动。
6.2 TCP 公平性
TCP 拥塞控制的一个隐含目标是公平性——所有 TCP 连接应公平共享瓶颈链路。Cubic 的 AIMD(加法增乘法减)策略天然趋向公平:增窗时线性增长,减窗时减半,多条连接最终收敛到公平分配。
但公平性并非总是成立:
- 不同 RTT 的连接:RTT 短的连接 ACK 回得快,cwnd 增长更快,占据更多带宽
- TCP vs UDP:UDP 不做拥塞控制,可能抢占 TCP 带宽
- BBR vs Cubic:BBR 不以丢包减窗,在有缓冲区的链路上可能比 Cubic 多占 2-3 倍带宽
- 多路径:MPTCP 子流共享瓶颈时需要特殊处理
6.3 缓冲区膨胀
缓冲区膨胀(Bufferbloat)是现代网络中一个被忽视的问题:路由器和交换机的缓冲区越来越大,数据包在队列中等待时间过长,导致 RTT 飙升。
Cubic 的”填满缓冲区”策略加剧了 Bufferbloat:cwnd 持续增长直到丢包,而大缓冲区意味着丢包发生时队列已经很长,RTT 可能从 50ms 膨胀到 500ms 甚至更高。交互式应用(SSH、游戏、视频会议)的延迟因此急剧恶化。
BBR 的设计天然对抗 Bufferbloat:它不依赖丢包信号,而是通过 RTprop 估计最小 RTT,尽量不产生队列。但 BBR v1 在与 Cubic 共存时可能过度占带宽,BBR v2/v3 做了改进。
6.4 显式拥塞通知
ECN(Explicit Congestion Notification,RFC 3168)让路由器在队列快满时标记数据包(而非丢弃),发送方看到标记后降低发送速率,避免丢包和重传。
# 启用 ECNsysctl net.ipv4.tcp_ecn # 0=禁用, 1=启用, 2=仅入向
# 查看当前 ECN 状态sysctl net.ipv4.tcp_ecn
# Wireshark 过滤 ECN 标记的包# tcp.flags.ecn == 1 或 ip.tos.ecn == 0x01ECN 使用 IP 头部的 TOS 字段中的 2 位:00 = 不支持 ECN,01/10 = 支持 ECN,11 = 拥塞经历(CE)。TCP 头部也有 ECE 和 CWR 标志用于协商和通告。
七、动手实践:观察拥塞窗口变化
7.1 用 iperf3 测试带宽
# 服务端iperf3 -s -p 5201
# 客户端:基本带宽测试iperf3 -c server_ip -p 5201 -t 30
# 客户端:指定拥塞控制算法iperf3 -c server_ip -p 5201 -t 30 -C bbr
# 客户端:输出 JSON 格式(便于脚本分析)iperf3 -c server_ip -p 5201 -t 30 -J > result.json7.2 用 ss 观察拥塞窗口
# 查看所有 TCP 连接的拥塞控制信息ss -ti
# 过滤特定连接ss -ti dst 10.0.0.1
# 输出字段解读:# cwnd = 拥塞窗口# ssthresh = 慢启动阈值# rtt = 往返时延# rttvar = RTT 方差# bbr = BBR 参数(bw, mrtt)# send = 发送速率估计
# 持续监控(每秒刷新)watch -n 1 'ss -ti dst 10.0.0.1'7.3 用 tcp_probe 追踪 cwnd 变化
# 加载 tcp_probe 内核模块sudo modprobe tcp_probesudo chmod 444 /proc/net/tcpprobe
# 监控特定端口的 cwnd 变化sudo cat /proc/net/tcpprobe > /tmp/cwnd_trace.log &CAT_PID=$!
# 运行 iperf3 测试iperf3 -c server_ip -p 5201 -t 10
# 停止监控kill $CAT_PID
# 分析 cwnd 变化# 日志格式:timestamp src dst sport dport cwnd ssthreshawk '{print $1, $6, $7}' /tmp/cwnd_trace.log | head -207.4 Wireshark TCP 流图
Wireshark 提供了强大的 TCP 流可视化功能:
# 抓取 TCP 流量sudo tcpdump -i eth0 tcp port 5201 -w tcp_congestion.pcap
# 在 Wireshark 中打开后:# 1. Statistics → TCP Stream Graphs → Round Trip Time Graph# 2. Statistics → TCP Stream Graphs → Throughput Graph# 3. Statistics → TCP Stream Graphs → Window Scaling Graph# 4. Statistics → TCP Stream Graphs → Time-Sequence (Stevens)
# Wireshark 显示过滤器tcp.analysis.retransmission # 重传数据段tcp.analysis.duplicate_ack # 重复 ACKtcp.analysis.fast_retransmission # 快速重传tcp.window_size == 0 # 零窗口tcp.flags.ecn == 1 # ECN 标记7.5 Python 模拟拥塞窗口变化
"""模拟 TCP Reno 拥塞窗口变化"""import matplotlib.pyplot as plt
def simulate_tcp_reno(max_rtt=50, loss_rtt=20, mss=1460): """模拟 TCP Reno 的 cwnd 变化""" cwnd = 1 # 初始 cwnd(MSS) ssthresh = float('inf') cwnd_trace = []
for rtt in range(max_rtt): cwnd_trace.append(cwnd)
if cwnd < ssthresh: # 慢启动:指数增长 cwnd *= 2 else: # 拥塞避免:线性增长 cwnd += 1
# 模拟丢包事件 if rtt == loss_rtt: ssthresh = max(cwnd // 2, 2) cwnd = 1 # 超时丢包,回到慢启动
return cwnd_trace
def simulate_tcp_newreno(max_rtt=50, loss_rtt=20): """模拟 TCP NewReno 的 cwnd 变化""" cwnd = 1 ssthresh = float('inf') cwnd_trace = [] fast_recovery = False
for rtt in range(max_rtt): cwnd_trace.append(cwnd)
if fast_recovery: # 快速恢复中 cwnd += 1 # 收到重复 ACK if cwnd >= ssthresh + 3: fast_recovery = False cwnd = ssthresh elif cwnd < ssthresh: cwnd *= 2 else: cwnd += 1
if rtt == loss_rtt: ssthresh = max(cwnd // 2, 2) cwnd = ssthresh + 3 # 快速恢复 fast_recovery = True
return cwnd_trace
# 运行模拟reno = simulate_tcp_reno()newreno = simulate_tcp_newreno()
# 绘图fig, ax = plt.subplots(figsize=(10, 5))ax.plot(reno, label='TCP Reno', marker='o', markersize=3)ax.plot(newreno, label='TCP NewReno', marker='s', markersize=3)ax.set_xlabel('RTT 轮次')ax.set_ylabel('cwnd (MSS)')ax.set_title('TCP Reno vs NewReno 拥塞窗口变化')ax.legend()ax.grid(True, alpha=0.3)plt.tight_layout()plt.savefig('tcp_cwnd_simulation.png', dpi=150)print("模拟完成,图表已保存")八、本章小结
8.1 拥塞控制算法演进总览
| 算法 | 年份 | 核心机制 | 拥塞信号 | 优势 | 局限 |
|---|---|---|---|---|---|
| Tahoe | 1988 | 慢启动 + 拥塞避免 | 超时/重复ACK | 首个拥塞控制 | 3重复ACK也回到慢启动 |
| Reno | 1990 | +快速重传/恢复 | 3重复ACK | 避免超时等待 | 单窗口多丢包恢复差 |
| NewReno | 1999 | +部分ACK处理 | 3重复ACK | 多丢包恢复改善 | 仍依赖丢包信号 |
| Cubic | 2006 | 三次函数增长 | 丢包 | RTT无关增长 | 填满缓冲区,有损链路差 |
| BBR | 2016 | 模型驱动 | 带宽+RTT模型 | 不依赖丢包,低延迟 | 与Cubic公平性问题 |
8.2 拥塞事件与响应
| 拥塞事件 | 检测方式 | cwnd 响应 | ssthresh 响应 | 状态转换 |
|---|---|---|---|---|
| 超时 | RTO 超时 | → 1 MSS | = cwnd/2 | → 慢启动 |
| 3 重复 ACK | 重复 ACK 计数 | = ssthresh + 3 | = cwnd/2 | → 快速恢复 |
| 部分 ACK(NewReno) | 快速恢复中收到 | +1 MSS | 不变 | 继续快速恢复 |
| 新 ACK(Reno) | 快速恢复中收到 | = ssthresh | 不变 | → 拥塞避免 |
| ECN 标记 | IP 头 CE 位 | = cwnd × β | = cwnd/2 | → 拥塞避免 |
8.3 Linux 拥塞控制 sysctl 参数
| 参数 | 默认值 | 说明 |
|---|---|---|
net.ipv4.tcp_congestion_control | cubic | 当前拥塞控制算法 |
net.ipv4.tcp_init_cwnd | 10 | 初始拥塞窗口(MSS) |
net.ipv4.tcp_no_metrics_save | 0 | 是否缓存上次 cwnd |
net.ipv4.tcp_ecn | 2 | ECN 设置(0=禁, 1=启, 2=入向) |
net.ipv4.tcp_nodelay | 0 | Nagle 算法(0=开启) |
net.ipv4.tcp_retries2 | 15 | 数据重传最大次数 |
net.ipv4.tcp_cubic_beta | 7/10 | Cubic 乘法减少因子 |
net.core.default_qdisc | fq_codel | 默认队列调度算法 |
从滑动窗口的端到端流控,到基于丢包的 Reno/Cubic,再到模型驱动的 BBR,TCP 拥塞控制走过了一条从”被动反应”到”主动建模”的演进之路。但 TCP 的拥塞控制始终受限于一个架构约束:拥塞控制状态与传输层绑定,连接切换路径时状态全部丢失。
这正是 QUIC 要解决的核心问题之一。在 QUIC与HTTP/3 中,将看到 QUIC 如何通过连接 ID 实现连接迁移、如何将拥塞控制从内核搬到用户空间实现快速迭代、以及 HTTP/3 如何在 QUIC 之上消除 HTTP/2 的队头阻塞——TCP 拥塞控制的经验与教训,全部沉淀在了 QUIC 的设计之中。
参考
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






