你有没有遇到过这样的情况?视频会议卡在“正在连接”,游戏里人物瞬移,或者上传一个大文件,进度条半天不动——其实问题不一定出在带宽上,很可能是系统底层的网络协议栈‘拖了后腿’。
发包不是越快越好,而是要‘刚刚好’
Linux 默认的 TCP 发送逻辑讲究稳妥:数据写进 socket 缓冲区后,不急着发,等凑够 MSS(最大报文段长度)或等定时器超时(比如 200ms 的 delayed ACK 机制),才打包发出。这对小流量、交互式应用友好,但对高吞吐场景(比如实时日志推送、内网大数据传输)就是瓶颈。
几个立竿见影的调优点
打开终端,试试这几个命令:
sysctl -w net.ipv4.tcp_nodelay=1
sysctl -w net.core.wmem_default=262144
sysctl -w net.core.wmem_max=4194304第一行关掉 Nagle 算法,让小包不憋着;后两行加大发送缓冲区,默认值太保守,尤其千兆以上网卡常吃不满带宽。
应用层也能帮一把
用 send() 时加 MSG_NOSIGNAL 防止被 SIGPIPE 中断;批量写入尽量用 sendfile() 或 splice(),绕过用户态内存拷贝。比如 Nginx 静态文件服务就靠这个提速一大截。
再举个生活化例子:公司内部部署了一个日志收集服务,每秒要发几万条 JSON 日志到 Kafka。刚上线时经常丢包、延迟飙升。后来把 tcp_nodelay 打开 + 调大 wmem_max,又在客户端代码里把日志攒够 1KB 再 flush,延迟立刻从平均 80ms 压到 12ms 以内。
别盲目调参数
增大缓冲区不等于一定更快——如果网络本身有丢包,过大的缓冲反而加剧 Bufferbloat(缓冲膨胀),导致 RTT 拉长、交互卡顿。建议配合 ping -q -c 10 www.example.com 和 ss -i 观察重传率和 rtt 变化,边调边看。