tcp_nopush必须与sendfile协同生效,仅对>100kb静态文件有效;需同时满足sendfile on、tcp_nodelay off及真实磁盘文件三前提,否则无效,盲目开启反增小文件首字节延迟。

tcp_nopush 不是独立生效的开关,它必须和 sendfile 协同工作,只对走内核零拷贝路径的大静态文件有效;盲目开启反而可能增加小文件首字节延迟。
必须满足的三个前提条件
缺一不可,否则 tcp_nopush 形同虚设:
- 全局或 location 块中明确启用
sendfile on;—— 这是基础。只有文件从页缓存直发网络栈,nopush 才有机会合并 TCP 包;proxy_pass、gzip、body_filter 都会绕过该路径。 - 显式关闭 Nagle 算法:
tcp_nodelay off;—— 二者逻辑冲突:nopush 要“攒包”,nodelay 要“立刻发”。现代 Nginx 虽支持共存,但对视频、安装包等大文件分发,设为 off 更稳妥。 - 仅用于合适场景:
tcp_nopush对 >100KB 的静态资源(如 mp4、iso、zip)效果明显;对 HTML、JS、图标、HTTPS 响应、动态内容基本无效,甚至轻微拖慢首屏。
推荐的配置位置与写法
不建议在 http 块全局开启,应按资源类型精准控制:
- 全站以静态资源为主时,可统一配置(但仍需确保其他条件满足):
tcp_nopush on;
tcp_nodelay off;
- 更推荐下沉到具体 location,例如只对下载类资源启用:
root /data/files;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
}
配合其他关键调优项提升效果
单靠 tcp_nopush 收效有限,需组合使用:
- 设置
sendfile_max_chunk 512k;:避免单次 sendfile 阻塞 worker,也利于内核组装更大 TCP 段。 - 对大文件 location 关闭访问日志:
access_log off;,防止 I/O 成为瓶颈。 - 启用文件句柄缓存:
open_file_cache max=10000 inactive=30s;,减少重复 open/stat 系统调用。 - 精简响应头:过大的自定义 header 会挤占 TCP 包空间,影响“响应头 + 文件开头数据”合并效果。
如何验证是否真正生效
不能只看配置写了没,要观察实际网络行为:
- 用
ss -i查看活跃连接,确认输出中有np标记(表示 nopush 已启用)。 - 用 Wireshark 抓包对比:开启后,HTTP 响应头与文件前几百 KB 数据应尽量落在同一个 TCP 段中,而非拆成多个小包。
- 压测时关注“小于 1500 字节的 TCP 包占比”是否下降,重传率是否稳定——这才是减少网络碎片的真实体现。











