tcp_nopush 须与 sendfile on 配合使用才能生效,仅对静态文件有效,需禁用 gzip、tcp_nodelay,并确保 Content-Length 存在;否则被忽略。

tcp_nopush 本身不直接降低传输延迟,而是通过减少小 TCP 包数量、提升单包载荷率来优化大文件分发效率——它真正缩短的是“首帧/首屏感知时间”,尤其在客户端能更快收到响应头 + 文件开头数据时效果明显。关键不是“开开关”,而是让它在正确路径上起作用。
必须同时启用 sendfile 才生效tcp_nopush 依赖内核零拷贝路径,只有 sendfile on 开启后,Nginx 才能把 HTTP 响应头和文件前段数据交由内核一次性组装进一个 TCP 报文段。如果 sendfile 关闭(比如用了 proxy_pass、gzip 或动态生成),tcp_nopush 就被忽略,日志里会提示 “tcp_nopush is ignored”。
只对真实静态文件路径有效
仅当 Nginx 直接读取磁盘文件(如用 root 或 alias 指向本地路径)且匹配明确后缀(.mp4、.zip、.iso、.webp 等)时才触发。API 接口、WebSocket、HLS 的 .m3u8、甚至带 add_header 的 HTML 都会绕过该路径。
配套设置必须对齐
-
tcp_nodelay off:显式关闭,避免 Nagle 算法被意外激活,干扰tcp_nopush的合并逻辑; -
gzip off:压缩必须走用户态,一开就禁用sendfile; - 响应头含
Content-Length:Nginx 需预知大小才能调用sendfile();若后端返回Transfer-Encoding: chunked,自动退化为普通读写模式; -
sendfile_max_chunk 512k:防止单次sendfile过大阻塞事件循环,也适配多数高清图或短视频的首段体积。
推荐按文件类型精细化配置
不要全局开启,避免误伤低延迟接口。例如:
location ~ \.(mp4|webm|zip|iso|tar\.gz|dmg|psd|tiff)$ {
root /data/files;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
gzip off;
expires 30d;
}验证是否真生效
- 用
strace -e trace=sendfile -p $(pgrep nginx)观察 worker 进程是否调用sendfile系统调用; - 抓包看 TCP 流:响应头与文件开头是否出现在同一报文段(Wireshark 中检查 TCP payload 是否包含
HTTP/1.1 200和文件 magic bytes); - 检查 Nginx error log,确认无
tcp_nopush is ignored类警告。
不复杂但容易忽略

















