Sunday面试指南

TCP 的 Nagle 算法和延迟 ACK 是什么?小请求为什么可能出现额外等待?

下面是一段教学用的模拟面试。

🧑‍💻 面试官:一个很短的请求,拆成两次 write 后,偶尔多等了一段时间。你会看什么?

🙋‍♂️ 我:小包被 Nagle 算法攒住了,关闭就行。

🧑‍💻 面试官:第一段已经发出去,为什么第二段才等?接收端延迟 ACK 又起什么作用?

🙋‍♂️ 我:一边等确认,一边可能暂缓确认。

🧑‍💻 面试官:那等待时间一定是 200ms 吗?所有延迟都能靠 TCP_NODELAY 解决吗?

Nagle 在决定什么时候发送小段数据,延迟 ACK 在决定什么时候确认收到的数据。特定交互下,它们可能互相延长等待。

面试速答(60 秒版)

Nagle 算法用于减少小 TCP 报文。典型规则是已有数据尚未被确认时,继续到来的小段数据可能被缓冲,等待确认或积累到合适的发送条件。

延迟 ACK 则发生在接收端:接收方可以暂缓确认,希望合并确认或与返回数据一起发送,具体时机受到协议要求和操作系统实现影响。

如果应用把一个小请求拆成多次写入,发送方等前一段的 ACK 才发后续小段,接收方又等待更多数据或延迟确认,就可能增加请求等待。

可以评估合并写入或设置 TCP_NODELAY,但要通过抓包与应用时间线确认。关闭 Nagle 不等于关闭延迟 ACK,也不能消除所有缓冲和网络延迟。

发送端Nagle与接收端TCP延迟ACK可能形成额外等待

知识点详解:沿着两小段数据看谁在等谁

Nagle 不是所有小数据都固定等一会儿

如果没有尚未确认的数据,第一小段可以及时发送。它不是“所有小包都先睡固定时间”的算法。

第一段发出以后,第二小段到来,而第一段还没得到确认,Nagle 的规则就可能让第二段先留在发送端。收到确认,或积累到相应发送条件后,再继续发送。

这个机制减少报文开销,但对某些交互式小请求,等待也可能变得显眼。TCP RFC 9293

延迟 ACK 为什么要等?

接收方没必要对每个小段都立即单独发一份确认。适当合并确认,或者把确认带在返回数据中,可以减少额外报文。

但接收方不能无限不确认。协议有相关约束,实际定时与提前触发规则取决于实现、连接状态和收到的数据。

所以不要背成“延迟 ACK 总等 200ms”,更不能据此断言所有相似延迟都来自同一个原因。

两者怎样组合出额外等待?

假设一个应用层请求分成 A、B 两小段,接收端拿到完整 A+B 后才处理并返回。

A 先到,B 在发送端等待 A 的确认。接收端暂缓 ACK,同时应用还在等 B,不能返回响应。直到确认被发出,B 才继续发送,请求才完整。

这是可能的时序,不是任何两次 write 都一定发生的结果。MSS、写入间隔、系统缓冲及确认行为都会影响它。

TCP 是字节流,应用 write 的边界也不保证等于 TCP 报文边界。诊断必须看实际线上报文,而不是仅看源码调用次数。

TCP_NODELAY 能改变什么?

它用于关闭连接上的 Nagle 行为。下面是已有 socket 的设置片段,不包含完整连接与请求实现。

TypeScript(Node.js net.Socket):

import type { Socket } from "node:net";

function enableLowLatency(socket: Socket): void {
  socket.setNoDelay(true);
}

Python(标准库 socket):

import socket

def enable_low_latency(sock: socket.socket) -> None:
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

它不会直接关闭对端的延迟 ACK,也不会让 TLS、应用缓冲、拥塞控制和链路排队消失。小包数量也可能增加,所以应根据实际流量评估。

如果原本可以把请求头和请求体合理合并写入,先减少不必要的小写入,也是一种更直接的调整。

怎样证明问题确实来自这里?

对齐应用写入、实际发送、ACK 到达和对端响应的时间。检查第二段是否因未确认数据而延迟,以及确认什么时候释放了等待。

还要排除连接建立、DNS、TLS、丢包重传和应用处理。只看到一个接近某个定时值的耗时,证据仍然不足。

TCP_NODELAY只作用于Nagle并不能取消所有应用TLS代理缓冲

图中抓包位置和数据发送节奏仅为排查示意,不是一次真实网络实验的抓包结果。

面试官继续追问

小包多,就一定该启用 Nagle 吗?

不一定。吞吐与交互延迟的目标不同,还要看应用如何写数据和连接怎么使用。

一次 write 就保证一个 TCP 包吗?

不保证。TCP、TLS 和系统可以拆分或合并数据,应用边界不等于报文边界。

关闭以后没变快,是不是设置没生效?

未必。瓶颈可能不在 Nagle,需要继续按实际时序定位,而不是重复修改同一个参数。

面试速记卡

  • Nagle:减少小报文,可能等待已有数据确认。
  • 延迟 ACK:接收端暂缓确认,不是发送端的小包合并。
  • 组合问题:应用拆写与两端等待在特定时序下叠加。
  • TCP_NODELAY:关闭 Nagle,不消除其他等待。
  • 验证依据:应用时间线+实际报文,而不是固定毫秒口诀。

公司面试真题

这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历