本文目录导读:

这是一个非常专业的问题。net.ipv4.tcp_abc(TCP Appropriate Byte Counting,适当字节计数)确实是一个直接影响TCP拥塞控制行为的参数。
要理解它“怎样拥塞”,需要先澄清一个常见的误解:这个参数本身不是一种新的拥塞控制算法(如CUBIC或BBR),而是一个修改拥塞窗口(cwnd)增长计算方式的机制。 它通过改变“如何判断丢包发生”来间接影响拥塞控制。
tcp_abc 影响的是当一次收到多个ACK(确认包)时,拥塞窗口如何增长。
以下是详细的技术解释:
基础知识:拥塞窗口的增长(标准RFC 5681)
在标准的TCP拥塞避免阶段(非BBR),拥塞窗口的增长遵循“每收到一个完整的新数据段的ACK,cwnd增加1 MSS(最大报文段长度)”的原则,这被称为按ACK计数(ACK-Clocking)。
- 问题: 假设一个应用发送了4个报文段,然后收到了一个ACK,这个ACK一次性确认了这4个报文段(使用了延迟确认或网络突发),按照标准规则,这个ACK只触发1次cwnd增长,而不是4次,这意味着,发送方没能及时利用网络中的可用带宽,特别是在长胖网络(高带宽高延迟)中,窗口增长非常缓慢。
- 本质: 标准规则以ACK数量为增长单位,而不是以实际传输的字节数为单位。
tcp_abc 的原理:按字节计数
tcp_abc 的核心思想是:拥塞窗口的增长应该基于这个ACK所确认的字节数,而不是ACK的个数。
- 常规模式(tcp_abc=0): 遵循标准RFC 5681,按ACK数量计数,导致增长缓慢,对网络突发不敏感。
- 按字节计数模式(tcp_abc=1,在Linux 2.6.25+中): 接收一个ACK,会将其确认的字节数计入一个计数器,当这个计数器达到
inflight(在途未确认字节数)时,cwnd增加1 MSS,这种方式更平滑,能更快地跟上实际发送带宽。 - 改进模式(tcp_abc=2,Linux 3.2+): 在模式1的基础上,还加入了一个限制:如果发送方正在使用拥塞窗口进行突发发送(通过TCP Small Queues或pacing机制,这种突发被限制),则禁止cwnd增长。 这能防止在ACK汇聚导致的窗口激增。
核心公式(简化): 当ACK到达时,cwnd += (bytes_acked * MSS / inflight)
tcp_abc 如何影响“拥塞”行为
它本质上是改变了拥塞窗口的扩张速率,从而影响拥塞过程:
场景A:tcp_abc=0(标准模式)
- 行为: 即使你一次性收到了确认100KB的ACK,也只涨1个MSS。
- 拥塞表现: 窗口增长缓慢,带宽利用率低,在高丢包或高延迟网络中,窗口无法快速恢复到丢包前的水平,导致吞吐量受限,这是最保守的模式。
- 优势: 对网络冲击小,不易造成突发拥塞,适合低延迟、高丢包的窄带网络(如传统Wi-Fi、卫星链路)。
场景B:tcp_abc=1(按字节计数)
- 行为: 收到确认100KB的ACK,如果当前
inflight(在途)是50KB,那么确认了2倍的inflight,cwnd会增加约2 MSS。 - 拥塞表现: 窗口增长加快,当网络突然变得空闲时(前序ACK延迟到达,但数据已全部发送),它能够快速填充空闲的带宽,这会导致更大的突发性,可能更容易造成中间路由器缓冲区的瞬时拥塞(bufferbloat)。
- 优势: 带宽利用率更高,特别适合长胖网络(LTE、光纤到户)。
- 风险: 在链路共享场景下,可能产生更大的抖动,加剧竞争性拥塞。
场景C:tcp_abc=2(改进模式)
- 行为: 与模式1相同,但当发送方处于突发状态时(即最近发送了较大数量的数据包),不增长cwnd。
- 拥塞表现: 在高峰期(刚从一个大的Burst中发送出去),窗口增长被抑制,这可以平滑窗口扩张,减少bufferbloat,它意味着“即使确认了更多数据,也不要立即认为网络更宽了,因为你刚扔了大量数据进去,需要稳定反馈”。
- 优势: 兼顾了按字节计数的带宽利用率,同时减少了其可能导致的内部拥塞风险,这是目前多数现代Linux发行版的推荐默认值。
实际配置建议
tcp_abc=0(默认,但已过时): 适用于对网络抖动极其敏感的实时应用(如VoIP、游戏),但会牺牲吞吐量。tcp_abc=1: 适用于需要最大化吞吐量的长胖网络(如大型文件传输、CDN回源),但可能加剧延迟抖动。tcp_abc=2: 推荐配置,适用于大多数通用场景,结合了高吞吐与较少的Bloat风险。
它与BBR等现代算法的关系
- 如果你使用BBR拥塞控制算法(
net.core.default_qdisc=fq+net.ipv4.tcp_congestion_control=bbr),BBR本身有自己的基于带宽和RTT(往返时间)的探测模型。 - BBR不依赖ACK计数来增长窗口。 它完全忽略
tcp_abc参数,BBR的窗口增长由探测带宽(Pacing Gain > 1)控制,与ACK计数无关。 - 而对于CUBIC、Westwood等算法,
tcp_abc仍然有效。
net.ipv4.tcp_abc 通过改变拥塞窗口对ACK的敏感度来影响拥塞:
- 数值越高(0→1→2),增长越激进(模式2+限制),对带宽利用率越高,但可能引入更大的瞬时队列(bufferbloat),当
inflight很大时,模式2会抑制增长来平衡。 - 数值越低(2→1→0),增长越保守,对网络冲击小,但在长胖网络中吞吐量严重受限。
一句话结论: 对于现代网络(高带宽、适度延迟),推荐使用 tcp_abc=2,如果你的网络是延迟极度敏感且带宽很小(如窄带物联网),tcp_abc=0 可能更平滑,但会浪费带宽;tcp_abc=1 已很少单独使用。
标签: ipv4.tcp_abc` 生成的两个关键词是: 拥塞控制