TCP 拥塞控制是网络稳定性的核心机制,其目标是避免网络过载导致的丢包和延迟恶化。传统拥塞控制算法基于丢包反馈,而现代算法开始关注延迟和带宽探测。
最早的拥塞控制算法,采用简单的丢包响应:
# Tahoe 伪代码 def on_packet_sent(): if cwnd < ssthresh: cwnd *= 2 # 慢启动 else: cwnd += 1 # 拥塞避免 def on_loss_detected(): ssthresh = max(cwnd / 2, 2) cwnd = 1
在 Tahoe 基础上增加快速恢复机制:
# Reno 快速恢复 def on_three_dup_acks(): ssthresh = max(cwnd / 2, 2) cwnd = ssthresh + 3 # 加上三个重复 ACK 对应的包 enter_fast_recovery() def on_ack_in_recovery(): cwnd += 1 # 每收到一个 ACK,cwnd 加 1 def on_recovery_done(): cwnd = ssthresh # 恢复结束,设置为新阈值
优势: 减少因单个丢包导致的性能波动
劣势: 在高 BDP 网络中效率低,丢包后恢复慢
Linux 默认算法,使用三次函数调整 cwnd:
import time class CUBIC: def __init__(self): self.cwnd = 10 self.ssthresh = 100 self.last_loss_time = time.time() self.w_max = self.cwnd self.C = 0.4 # CUBIC 系数 def on_ack(self): t = time.time() - self.last_loss_time # CUBIC 三次函数 target = self.w_max + self.C * (t ** 3) if self.cwnd < target: # 凸增长阶段 self.cwnd = min(target, self.cwnd + (target - self.cwnd) / self.cwnd) else: # 凹增长阶段 self.cwnd += 0.1 def on_loss(self): self.w_max = self.cwnd self.ssthresh = self.cwnd * 0.7 self.cwnd = self.ssthresh self.last_loss_time = time.time()
优势: 在高带宽延迟积网络中吞吐量更高
劣势: 仍依赖丢包作为拥塞信号
Google 于 2016 年发布的革命性算法,彻底抛弃了"丢包=拥塞"的假设。
import time class BBR: def __init__(self): self.min_rtt = float('inf') self.max_bw = 0 self.cwnd = 10 self.state = 'STARTUP' self.cycle_stamp = time.time() def update_min_rtt(self, sample_rtt): if sample_rtt < self.min_rtt: self.min_rtt = sample_rtt def update_max_bw(self, delivered, elapsed): bw = delivered / elapsed self.max_bw = max(self.max_bw, bw) def calculate_bdp(self): return self.max_bw * self.min_rtt def on_ack(self, ack): # 更新带宽和 RTT 测量 delivered = ack.bytes_delivered elapsed = ack.elapsed_time self.update_max_bw(delivered, elapsed) self.update_min_rtt(ack.rtt) # 状态机 if self.state == 'STARTUP': self.cwnd *= 2 # 指数增长寻找带宽 if self.is_full_pipe(): self.state = 'DRAIN' elif self.state == 'DRAIN': self.cwnd *= 0.7 # 排空队列 if self.cwnd <= self.calculate_bdp(): self.state = 'PROBE_BW' elif self.state == 'PROBE_BW': # 周期性探测带宽 cycle_time = time.time() - self.cycle_stamp if cycle_time > self.min_rtt: self.state = 'PROBE_RTT' elif self.state == 'PROBE_RTT': self.cwnd = 4 # 降低 cwnd 测量最小 RTT if time.time() - self.cycle_stamp > 0.2: self.state = 'PROBE_BW' self.cycle_stamp = time.time() def is_full_pipe(self): # 检测是否达到管道容量 return self.max_bw * 1.25 < self.calculate_bdp()
优势:
改进版本,解决了 v1 的一些问题:
class BBRv2(BBR): def __init__(self): super().__init__() self.inflight_lo = 0 self.inflight_hi = float('inf') def on_ack(self, ack): super().on_ack(ack) # 基于丢包调整发送速率 if ack.loss_rate > 0.02: self.cwnd *= 0.7 # 维护 inflight 窗口 self.inflight_lo = min(self.inflight_lo, ack.bytes_inflight) self.inflight_hi = max(self.inflight_hi, ack.bytes_inflight) # 避免过度拥塞 if self.cwnd > self.inflight_hi * 1.2: self.cwnd = self.inflight_hi * 1.1
# 检查当前拥塞控制算法 sysctl net.ipv4.tcp_congestion_control # 启用 BBR sudo sysctl -w net.ipv4.tcp_congestion_control=bbr # 持久化配置 echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee -a /etc/sysctl.conf
// Spring Boot 应用启用 TCP_NODELAY @Configuration public class TomcatConfig { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() { return factory -> { factory.addConnectorCustomizers(connector -> { Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); protocol.setConnectionTimeout(30000); protocol.setKeepAliveTimeout(60000); protocol.setMaxKeepAliveRequests(1000); // 禁用 Nagle 算法,减少延迟 protocol.setSocketOptions("tcpNoDelay=true"); }); }; } }
# 增加网络缓冲区大小 sudo sysctl -w net.core.rmem_max=134217728 sudo sysctl -w net.core.wmem_max=134217728 sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 67108864" sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 67108864" # 启用窗口缩放 sudo sysctl -w net.ipv4.tcp_window_scaling=1 # 启用选择性 ACK sudo sysctl -w net.ipv4.tcp_sack=1
| 算法 | 吞吐量 | 平均 RTT | 丢包率 |
|---|---|---|---|
| Reno | 200 Mbps | 180 ms | 2% |
| CUBIC | 800 Mbps | 150 ms | 0.5% |
| BBR | 950 Mbps | 105 ms | 0.1% |
| 算法 | 吞吐量 | 平均 RTT |
|---|---|---|
| Reno | 15 Mbps | 280 ms |
| CUBIC | 45 Mbps | 200 ms |
| BBR | 92 Mbps | 55 ms |
拥塞控制算法从 Tahoe 到 BBR 的演进,反映了网络技术的不断进步。传统算法基于丢包反馈,在高速网络中效率低下;BBR 通过主动探测带宽和 RTT,实现了更高的吞吐量和更低的延迟。在实际应用中,根据网络环境选择合适的算法,并进行合理的参数调优,是提升网络性能的关键。