必须同时启用sendfile on、tcp_nopush on和tcp_nodelay off三指令,并避开代理、gzip、内容改写及非本地文件等退化条件,才能真正触发内核零拷贝;单独配置任一指令均无效,且仅对真实静态文件生效。

要让 Nginx 真正走内核零拷贝路径,提升静态文件传输效率,不能只写 sendfile on; —— 必须三要素齐备、退化条件全避开,才能稳定触发 sendfile() 系统调用。
必须同时启用的三个核心指令
这三项缺一不可,且需放在同一作用域(http、server 或 location 块中):
- sendfile on;:激活内核直送能力,跳过用户态缓冲区
- tcp_nopush on;:依赖 sendfile 路径,把响应头和文件开头数据合并进同一个 TCP 报文段,减少小包数量
- tcp_nodelay off;:关闭 Nagle 算法;若设为 on,会强制立即发包,直接破坏 tcp_nopush 的攒包逻辑
哪些配置会让 sendfile 自动失效
哪怕三指令全对,只要出现以下任一情况,Nginx 就会悄悄回退到传统的 read() + write() 模式:
- 启用了
gzip on、gunzip on或gzip_static on - 使用了
proxy_pass、fastcgi_pass、grpc_pass等代理指令 - 配置了
sub_filter、add_before_body等内容改写功能 - 文件不在本地 ext4/xfs 磁盘上(如 NFSv3、FUSE、Docker overlay2 默认驱动、符号链接指向非真实路径)
- 响应缺失
Content-Length头(例如后端未返回长度,或启用 chunked encoding) - 客户端发起 Range 请求(如视频拖拽)
按资源类型做精准 location 配置
不建议在全局 http 块盲目开启,应针对静态资源后缀做细粒度控制:
- 图片类:
location ~* \.(jpg|jpeg|png|webp|gif|avif|svg)$中启用三指令,并确保gzip off - 大文件类:
location ~ \.(mp4|zip|iso|tar\.gz|dmg)$可额外加sendfile_max_chunk 512k;,防止单次传输阻塞事件循环
验证是否真正生效
不能只看配置语法正确,要确认运行时行为:
- 用
strace -p $(pgrep nginx | head -1) -e trace=sendfile64观察 worker 进程是否持续调用sendfile64,而非read+write - 压测对比 CPU 使用率:开启后 sy(系统态)占比应明显下降,QPS 提升通常达 20%–50%
- 检查错误日志是否有
sendfile() failed类报错,提示底层文件系统或权限问题











