一条TCP连接在传输数据时,流量发送方窗口大小直接决定吞吐量。控制我见过太多人调优网络只盯着带宽和延迟,流量却忽略内核里那套默认参数——它们才是控制真正的隐形瓶颈。比如默认的流量初始拥塞窗口(initcwnd)只有10个段,对现代高速网络来说,控制这就像开着跑车却用一档起步。流量
先看个真实场景。控制某次给客户调一个跨机房同步服务,流量两地延迟约30ms,控制带宽1Gbps。流量理论上单连接极限是控制带宽×RTT≈3.75MB的数据在途量。但实测吞吐只有40MB/s,流量远低于预期。控制抓包后发现,流量发送窗口经常卡在128KB左右——这是典型的接收窗口限制。服务端默认的rmem_max只有4MB,而接收缓冲区实际只分配了208KB。数据包到达后,接收方通告的窗口太小,发送方被迫等待ACK,链路利用率自然上不去。
解决办法不复杂,改几个sysctl参数就完事。但真正有意思的是,流量控制不只是调整缓冲区大小。TCP的拥塞控制算法才是那个“看不见的手”。Linux默认用cubic,它在高带宽长延迟网络(也就是所谓的BDP网络)下表现不错,但在丢包率稍高的无线环境里,cubic会过度保守——每次丢包都砍半拥塞窗口,恢复又慢。换成bbr试试?它不靠丢包来判断拥塞,而是主动探测带宽,效果立竿见影。我有次在4G网络下测试,从上海连到东京,bbr比cubic吞吐提升了近3倍,延迟还更低。
但别急着全盘换bbr。它在深队列场景下会占用过多缓冲区,挤压其他流量。我见过一个奇葩案例:机房内部备份流量开了bbr,结果把核心交换机的队列塞满,前端业务延迟瞬间飙到200ms以上。后来给备份流量单独设了优先级,才平息这场“内战”。
再往下挖,还有个容易被忽略的细节——TCP小包合并(TSO/GSO)。默认开启的TSO把多个小包合并成大段发送,能显著降低CPU开销。可一旦网络设备不支持超长帧,或MTU设置不对,反而会触发分片,导致性能雪崩。我排查过一起诡异现象:服务器间传输只有20MB/s,CPU占用却高达30%。最后发现是虚拟网卡驱动没开TSO,而TCP segmentation offload被内核接管,每个包都要经过软件分段,纯属浪费算力。
流量控制本质是动态博弈。发送方想拼命塞数据,接收方得告诉它“我处理不过来”,网络中间节点则用ECN或丢包提醒“这里堵了”。Linux把这些机制都做成了可配置项,但默认值往往偏向保守——毕竟服务器要适配各种环境。你得根据自己业务特性去调。比如视频直播,延迟敏感,那就要小缓冲区加快速重传;而离线批处理,吞吐优先,可以大胆拉大缓冲区甚至禁用Nagle算法。
最后说个反直觉的现象:调优不是越大越好。我曾经把发送缓冲区设成16MB,结果高并发下内存直接爆掉——每个连接都占这么多,几千个连接就是几十GB。更坑的是,某些TCP拥塞控制算法在窗口过大时,会触发burst突发,反而加剧网络抖动。所以,动手之前先算清你的BDP,再决定参数值。别迷信网上的“万能调优脚本”,那玩意儿坑过不少人。
