首页/系统/Linux 内核与性能调优速查/TCP_NODELAY 与交互延迟
网络栈调优98 条

TCP_NODELAY 与交互延迟

小请求响应型连接可开启 TCP_NODELAY, 避免发送端攒包等待与延迟确认叠加造成额外往返。

关闭 Nagle 算法

Nagle 算法会把小块数据攒起来,等前一个报文被确认后再发送,用来减少小包数量。对请求响应型连接,这个等待会与对端的延迟确认叠加,产生规律性的额外往返。TCP_NODELAY 关闭该算法,让每次写操作尽可能立即发出。它适合小请求频繁往返的连接,不适合大流量批量传输。

基本信息

适用平台Linux / Unix,其它系统同样提供同名选项
取值1 关闭 Nagle 立即发送,0 使用默认算法
默认状态启用 Nagle
适用画像小请求响应型、往返次数多、单次数据小
副作用小包数量上升,头部与处理开销占比提高

典型使用场景

  • 远程调用与数据库客户端:命令与结果都是小数据,往返延迟敏感。
  • 长连接上的小响应服务,需要压低尾部延迟。
  • 排查规律性的固定量级延迟尖刺,判断是否由攒包与延迟确认叠加造成。
  • 压测中验证关闭算法的收益,避免只凭经验一刀切。
  • 反例场景:大文件与批量数据传输,通常不需要且不划算。

C 用例

C 用例
int one = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
    perror("setsockopt TCP_NODELAY");
}
/* 逐连接按业务特征设置,比全局一律开启更容易评估效果 */

量化对比

量化对比
ss -tin state established 'sport = :8080' | head   # 看往返时间与确认超时相关字段
tcpdump -ni eth0 -c 50 'tcp port 8080'             # 观察相邻报文间隔与包长分布
sar -n DEV 1 5                                     # 对比开启前后的包速率变化

按连接类型取舍

连接特征是否关闭算法理由
小请求高频往返建议关闭减少等待确认造成的额外往返
大块顺序传输不建议攒包带来的开销节省更有价值
混合负载按连接区分一刀切会让两类流量互相拖累
应用层合并写请求往往比全局关闭 Nagle 更有效:减少写调用次数从根源上减少小包,且不影响其它连接。
对全部连接一律关闭会明显抬高包量与 CPU 占用;建议先在少量连接上验证,用同一负载对比包速率与延迟分布再推广。

易错点

  • 对所有连接一刀切关闭:小包数量明显上升,网络与中断开销增加,整体表现可能变差。
  • 用它解决应用层逐字节写的问题:根源在写入方式,关闭算法只是把开销转嫁给网络。
  • 忽略与延迟确认的交互:两端策略叠加才造成规律延迟,只改一侧往往看不出变化。
  • 只在单次测试里判断收益:缺少同负载的包量与延迟分布对比,结论不可靠。
  • 对短连接也照搬设置:握手与挥手成本占比更高,关闭算法带来的收益有限。

数据来源与参考

  • man 7 tcp
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌