tcp_nodelay仅在长连接、响应≤1KB、后端已flush的精准场景下禁用Nagle算法,消除20–200ms攒包等待;必须按location或upstream启用,禁用sendfile和tcp_nopush,并配合内核调优与实证验证。
开启 tcp_nodelay 并不能“强制实现无延迟实时传输”,它只是禁用 Nagle 算法,让满足条件的小响应在长连接中**不等待 ACK、不攒包,立即发出**,从而消除 20–200ms 的人为卡顿。效果真实,但有明确边界——配错位置、忽略前提,就等于没开。
缺一不可,否则配置无效:
Connection: keep-alive 或 HTTP/2;需配置 keepalive_timeout 60;(建议 60–65 秒),并确认客户端实际复用连接(可用 ss -i dst <ip>:<port> 查看是否带 nodelay 标志)favicon.ico、manifest.json、/health 接口返回的 {"ok":true}、SSE 事件帧、WebSocket ping 帧等;大于 50KB 的图片或 JS bundle 不受 Nagle 影响,开了也没用res.flush(),Go 中调用 rw.(http.Flusher).Flush();若 Nginx 自身缓冲未释放(如 proxy_buffering on),tcp_nodelay 就失去作用对象必须按需写在 location 或 upstream 块中,避免全局开启干扰大文件传输:
以下配置与 tcp_nodelay 冲突,共存会导致其失效或被静默忽略:
sendfile on 时不要开 tcp_nodelay:零拷贝路径下,内核才直接控制 TCP 发送行为;若走用户态读取(如 proxy_pass、gzip 处理),tcp_nodelay 无法作用于 socket 缓冲区tcp_nopush on 与 tcp_nodelay on 同时启用:二者逻辑相斥(一个攒包、一个立刻发),Nginx 在非 sendfile 场景下可能静默忽略 tcp_nodelay;如需兼顾,只在 sendfile on 下共存,并理解 tcp_nodelay 优先级更高,仅影响末尾不满包proxy_buffering off;否则响应卡在 Nginx 缓冲区,根本到不了 TCP 层别只看配置写了没,要实证:
ss -i dst <server_ip>:<port> 查看 ESTAB 连接是否带 nodelay 标志tcp_nodelay 时用 curl -w "@format.txt" 请求健康接口,记录 time_starttransfer 波动;开启后重复,应看到 P95 延迟明显收敛