要让静态大文件在系统缓冲区积满后合并发送,关键是启用sendfile和tcp_nopush并确保零拷贝路径完整:必须同location中开启二者,配content-length、禁gzip/动态处理、调tcp_nodelay off及缓冲参数。

要让静态大文件在系统缓冲区积满后合并发送,核心不是“等缓冲区填满”,而是让内核具备把响应头和文件起始数据打包进同一个 TCP 报文段的能力。这依赖一条完整的零拷贝通路,而 tcp_nopush 只是这条通路上的“调度开关”——它本身不攒数据,但能配合 sendfile 触发内核级的 TCP_CORK 行为。
关键在于构建并守住这条通路,而不是调参数。
必须同时启用 sendfile 和 tcp_nopush
-
sendfile on;要写在具体服务大文件的location块里,不能只靠http块继承 -
tcp_nopush on;也必须在同一location中显式声明 - 如果只开
tcp_nopush而sendfile关闭,Nginx 日志会明确提示 “tcp_nopush is ignored”,配置实际无效
确保走真正的零拷贝路径
- 请求必须命中本地磁盘上的真实文件:用
root或alias指向有效路径,且后缀匹配(如.mp4、.zip、.iso) - 响应头必须含明确的
Content-Length:Nginx 需预知大小才能调用sendfile();若后端返回Transfer-Encoding: chunked或缺失该头,自动退化为read/write模式 - 代理对象存储时,需设
proxy_buffering off;,并确保上游返回Content-Length
关闭所有破坏零拷贝的模块
-
gzip off;—— 压缩强制进入用户态,sendfile自动禁用 -
sub_filter off;、ssi off;、access_by_lua_block { }移除 —— 任何内容改写或动态处理都会切断内核直通路径 -
proxy_buffering off;(仅限代理场景)—— 否则数据先缓存在用户态,sendfile不触发
配套参数必须对齐,避免“攒包”被干扰
-
tcp_nodelay off;:显式关闭 Nagle 算法,允许内核暂存数据等待凑满 MSS;设为on会强制立即发包,直接抵消tcp_nopush效果 -
sendfile_max_chunk 512k;:限制单次传输量,防止阻塞事件循环,也适配多数高清视频/安装包的起始段大小 -
output_buffers 2 128k;:增大发送缓冲区,默认2×32k对大文件常不够,易导致过早冲刷、破坏合并效果
按文件类型精细化启用,拒绝全局配置
- 在匹配大文件后缀的
location中启用,例如:location ~ \.(mp4|webm|zip|iso|tar\.gz|dmg)$ { sendfile on; tcp_nopush on; tcp_nodelay off; gzip off; sendfile_max_chunk 512k; output_buffers 2 128k; } - 不要在
/api/、/ws/、HLS 的.m3u8路径中启用 —— 这些场景首屏延迟更敏感,反而可能因“攒包”引入毫秒级延迟
不复杂但容易忽略











