tcp_nopush必须与sendfile协同生效,且仅对≥100kb静态大文件有效;需同时配置sendfile on、tcp_nopush on、tcp_nodelay off,并禁用gzip、调大output_buffers、设置sendfile_max_chunk 512k,按location精细化启用并验证np标记与tcp包合并效果。

tcp_nopush 不是独立开启就能生效的参数,它必须和 sendfile 协同工作,并满足一系列运行时条件,才能在大文件发送中真正减少小包、提升单连接吞吐效率。
只对真实静态大文件生效
它只在 Nginx 直接服务磁盘文件(如 root 或 alias 指向本地路径)、且文件体积足够大(建议 ≥100 KB)时起作用。视频、ISO、ZIP、高清图片等典型场景适用;API 响应、proxy_pass 转发、gzip 压缩内容、动态生成资源均会绕过零拷贝路径,使 tcp_nopush 失效。
必须同时配置的三项基础指令
-
sendfile on;—— 启用内核零拷贝,这是前提中的前提 -
tcp_nopush on;—— 允许内核暂存响应头与文件数据,合并发送 -
tcp_nodelay off;—— 避免与tcp_nopush逻辑冲突(Nagle 算法此时需保留)
配套调优不可少
-
sendfile_max_chunk 512k;—— 控制单次sendfile最大数据量,防止阻塞 worker,也利于内核组装大包 -
output_buffers 2 128k;—— 默认缓冲太小(2×32k),大文件易提前冲刷,导致无法攒包 -
gzip off;—— 压缩强制走用户态,直接禁用sendfile,连带让tcp_nopush归零 -
access_log off;—— 对大文件 location 关闭日志,避免 I/O 成为瓶颈
推荐按 location 精细化启用
不要全局写在 http 块里,而是下沉到具体资源路径:
location ~ \.(mp4|webm|avi|zip|iso|tar\.gz|dmg|woff2)$ {
root /data/assets;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
sendfile_max_chunk 512k;
output_buffers 2 128k;
gzip off;
access_log off;
expires 7d;
}
验证是否真正起效
-
ss -i查看连接,确认输出含np标记(表示 TCP_CORK 已启用) - Wireshark 抓包:HTTP 响应头与文件开头数据应落在同一个 TCP 段中,而非拆成多个
- 压测时观察“小于 1500 字节的 TCP 包占比”是否明显下降
不复杂但容易忽略











