tcp_nopush与sendfile必须协同启用且满足sendfile on、服务真实静态文件、响应含Content-Length三前提,才能实现零拷贝与TCP报文合并;仅在location级按文件类型精细化配置,禁用gzip并配tcp_nodelay off才可生效。

tcp_nopush 和 sendfile 是一对必须协同工作的内核级优化指令,专为提升大文件(如视频、安装包、高清图片)下载时的网络传输效率而设计。它们不改变带宽或延迟,而是减少小 TCP 包数量、降低 CPU 拷贝开销、提高单包载荷率——核心目标是让客户端更快拿到响应头 + 文件开头数据,缩短首屏/首帧时间。
必须同时满足的三个硬性条件
配置写了不等于生效。Nginx 在每次响应时都会动态判断是否启用零拷贝路径,缺一不可:
- 当前 location 中显式启用 sendfile on:不能仅靠 http 块继承,需在服务大文件的具体 location 内写明;
- 请求必须命中真实磁盘静态文件:例如 root 或 alias 指向本地路径,且后缀匹配(如 .mp4、.zip),proxy_pass、FastCGI、Lua 处理等均不触发;
- 响应头中必须含明确的 Content-Length:Nginx 需预知文件大小才能调用 sendfile() 系统调用;若后端流式响应、返回 chunked 编码或缺失该头,自动回退到 read/write 模式。
配套参数必须对齐,否则 tcp_nopush 被忽略
tcp_nopush 不是独立开关,它依赖 sendfile 提供的“连续数据流”才能攒包。以下设置必须同步到位:
- gzip off:压缩必须在用户态完成,开启 gzip 会强制禁用 sendfile,tcp_nopush 自动失效;
- tcp_nodelay off:Linux 下 tcp_nopush 实际启用 TCP_CORK,而 tcp_nodelay 强制立即发包,二者互斥;显式设为 off 可避免被上级块继承值干扰;
- 禁用 proxy_buffering(如代理后端):若用 Nginx 代理对象存储等大文件源,需加 proxy_buffering off; 并确保 upstream 返回 Content-Length。
推荐按资源类型精细化配置
全局开启易误伤 API、WebSocket、HLS 的 m3u8 等低延迟场景。应只在明确的大文件 location 中启用:
- 匹配常见大文件后缀:location ~ \.(mp4|webm|avi|mov|zip|iso|tar\.gz|dmg)$;
- 内部显式声明:sendfile on; tcp_nopush on; tcp_nodelay off; gzip off;;
- 可叠加缓存策略:expires 7d; add_header Cache-Control "public, immutable";。
如何验证是否真正生效
不能只看配置是否存在。需结合运行时行为确认:
- 用 strace -e trace=sendfile -p $(pgrep nginx) 观察 worker 进程是否调用 sendfile 系统调用;
- 用 Wireshark 抓取响应流量:开启后,HTTP 状态行、响应头与文件前几 KB 数据应出现在同一 TCP 段中,且小包(如
- 检查 Nginx 错误日志:若出现 "tcp_nopush is ignored",说明未满足 sendfile 触发条件。










