tcp_nopush 优化静态资源需完整配置链:必须启用 sendfile on,禁用 gzip/proxy_pass 等用户态处理,确保 content-length 准确,协调 tcp_nodelay,并按文件类型分路径精细化配置。

要让 tcp_nopush 真正优化静态资源的网络包发送,关键不是简单加一行 tcp_nopush on,而是构建一条能走通内核零拷贝路径的完整配置链。它只在特定条件下生效,错一个环节就静默失效。
必须同时启用 sendfile
tcp_nopush 完全依赖 sendfile on 才能起作用。Nginx 只有在直接读取磁盘文件、不经过用户态处理时,才能把响应头和文件数据交给内核一次性组装进 TCP 报文段。如果用了 proxy_pass、gzip、add_header 或 FastCGI,这条路径就断了,tcp_nopush 会被忽略,日志里会出现 “tcp_nopush is ignored” 提示。
- 在服务静态文件的
location块中显式写sendfile on;,不要只靠 http 块继承 - 确保该 location 使用
root或alias指向真实磁盘路径,例如root /data/static; - 避免在该 location 中启用任何需要用户态处理的功能(如压缩、重写头、鉴权逻辑)
只对明确长度的静态文件有效
tcp_nopush 要攒包,就得提前知道整个响应体有多大。Nginx 必须能生成或接收到准确的 Content-Length 头,否则无法调用 sendfile() 系统调用,自动退回到普通读写模式。
- 纯静态服务(
root+try_files)天然满足条件,会自动计算并设置Content-Length - 若通过反向代理拉取(比如从对象存储),后端响应必须带
Content-Length,且不能是Transfer-Encoding: chunked - 确保
proxy_buffering on;,并配足proxy_buffer_size和proxy_buffers,让 Nginx 能缓存完整响应再发
配套参数必须对齐
tcp_nopush 不是独立开关,它和 tcp_nodelay 逻辑冲突,和 gzip 互斥,必须整体协调:
-
tcp_nodelay off;:显式关闭 Nagle 算法,避免干扰tcp_nopush的合并行为(Linux 下tcp_nopush实际启用TCP_CORK) -
gzip off;:压缩必须在用户态做,一开就禁用sendfile,连带让tcp_nopush失效 - 可选但推荐:
sendfile_max_chunk 512k;,防止单次sendfile过大阻塞事件循环,也适配多数首帧/首屏数据体积
按文件类型精细化配置
不要全局开启。不同资源对延迟和吞吐的敏感度不同,应分路径配置:
- 对大文件(视频、安装包、高清图):专注吞吐,用
tcp_nopush on; tcp_nodelay off; - 对中小关键资源(CSS、JS、woff2、webp):兼顾首字节与完整性,可同时开
tcp_nopush on; tcp_nodelay on; - 对极小资源(
favicon.ico、robots.txt):tcp_nodelay on效果最明显,延迟可降 100–200ms
示例配置:
location ~ \.(mp4|zip|iso|webp|tiff)$ {
root /data/files;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
gzip off;
expires 30d;
}











