跳到主内容
快讯直播
AI智模界
AI 词典

Nagle 算法与 TCP_NODELAY:为什么你的小数据包会被攒着不发

一句话定义:Nagle 算法是 TCP 发送方的一种“凑够再发”策略,用来合并网络上的小数据包;TCP_NODELAY 是套接字上的一个开关,关掉这套策略,让数据立即发出。

它在攒什么

TCP 每发一段数据,都要等对方回一个确认(ACK)。Nagle 算法的规则只有一条:只要还有上一段小数据没被确认,新的小数据就先别发,攒着;攒够一个最大报文段(MSS)就发,或者等确认回来了再发。

打个比方:这个连接像一辆固定路线的货车。货物太少时,司机不愿为一个小纸箱就跑一趟,要等上一趟收到回执,或者等车厢装满才发车。省油是真省,但那个小纸箱就一直压在仓库里。

问题在于,很多交互场景天生只产生小包:游戏里一次按键几十字节,语音通话是一帧一帧的音频,远程桌面是鼠标移动,大模型的流式输出是一个 token 一个 token 往外写。这些数据加起来永远凑不满一个 MSS,于是只能互相等待,延迟被硬生生叠出来。

更麻烦的是“延迟确认”叠加:接收方本来也倾向于等一小会儿,看看有没有数据可以顺带一起确认。发送方等确认才发,接收方等更多数据才确认,两边互相等待,一次往返就被拖长到几十毫秒量级。单独看不算大,但每秒几十次交互时,手感就会严重变差。

开关:TCP_NODELAY

几乎所有语言的 socket API 都有 TCP_NODELAY 选项,设成 true 就等于告诉内核:“别攒,我写多少你发多少。”这是逐连接的发送方设置,只影响本机往外发的方向,跟对方怎么设置无关。

主流 RPC 框架和长连接库大多默认帮你打开它,因为它们的用户九成是延迟敏感型业务。但如果你自己直接写 socket,或者用某个默认值保守的驱动,就需要确认一下。

和相邻概念的区别

机制位置作用典型用法
Nagle 算法TCP 发送端,内核自动未确认小包时不发新小包默认开启,省小包
TCP_NODELAY套接字选项关闭 Nagle游戏、语音、实时 RPC
TCP_CORKLinux 套接字选项显式“封住”发送,攒够再放拼接文件头 + 正文
延迟确认TCP 接收端稍等再回 ACK,搭便车通常由系统控制
应用层批量你的代码先拼接,再一次写入日志、埋点上报

注意 Nagle 不是拥塞控制。拥塞控制管“整条链路该发多快”,Nagle 只管“这一个连接的小包要不要合并”,两者互不替代。

关掉之后,代价是什么

代价真实存在:包数变多,每个包都有约 40 字节的 TCP/IP 头,有效载荷占比下降;路由器要转发更多小包;在已经拥塞的链路上更容易添乱。所以“全站关 Nagle”并不是好习惯。

合理的判断标准是看流量形状:交互频繁、单次数据小、用户能感知到延迟,关掉;批量传输、日志上报、吞吐优先,留着反而更省。做流式输出和大模型推理服务时,尤其值得检查这一项,因为一个字一个字推给前端的那种“卡一下、涌一下”的观感,经常就来自这里。具体默认值以各框架官方文档为准。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。