网络通信中,协议栈是数据传输的核心部分。很多人在开发网络应用时,只关注业务逻辑,却忽略了底层协议栈的效率问题。结果就是,哪怕代码写得再漂亮,系统一到高并发就卡顿,用户抱怨加载慢,其实问题可能出在协议栈上。
减少上下文切换
频繁的用户态和内核态切换会拖慢协议栈处理速度。比如在处理大量小数据包时,每次中断都触发一次切换,CPU 花在调度上的时间比真正处理数据还多。可以启用 NAPI(New API)模式,让网卡在高负载时改用轮询方式收包,减少中断频率。
# 在 Linux 中启用 NAPI 收包模式
ethtool -C eth0 rx-usecs 50
调整 TCP 缓冲区大小
默认的 TCP 接收和发送缓冲区往往偏小。如果应用需要传输大文件或视频流,容易出现 buffer full 导致丢包重传。适当调大缓冲区能提升吞吐量。
# 修改系统级 TCP 缓冲区设置
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.tcp_rmem="4096 87380 134217728"
sysctl -w net.ipv4.tcp_wmem="4096 65536 134217728"
启用 TSO 和 GSO
TSO(TCP Segmentation Offload)和 GSO(Generic Segmentation Offload)可以把分段工作交给网卡处理,减轻 CPU 负担。相当于把快递打包的工作从你自己手上交给了物流点,省时省力。
# 查看网卡是否支持 TSO/GSO
ethtool -k eth0 | grep tcp-segmentation-offload
# 启用功能
ethtool -K eth0 tso on
ethtool -K eth0 gso on
避免频繁建立连接
短连接在高并发场景下会产生大量 TIME_WAIT 状态,消耗资源。像做外卖平台,每来一单就重新连一次后端服务,显然不现实。改用连接池或长连接,复用已建立的通道,能显著降低协议栈压力。
使用 SO_REUSEPORT 提升监听效率
多个进程或线程监听同一个端口时,传统方式容易产生“惊群”现象。SO_REUSEPORT 允许多个套接字绑定同一地址端口,由内核负责负载均衡,适合多核服务器部署服务实例。
int sock = socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
bind(sock, (struct sockaddr*)&addr, len);
监控与调优并行
优化不是一劳永逸的事。可以用 sar、netstat、ss 这些工具定期查看网络状态。比如发现 retransmit 数持续上升,就得回头检查是不是缓冲区不够或者网络拥塞。
协议栈调优不像换硬件那样立竿见影,但它带来的稳定性提升是实打实的。特别是在云服务器成本居高不下的今天,榨干每一滴性能,才是精打细算的做法。