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

sendfile 是 Nginx 实现静态文件高效传输的核心机制,它通过内核态零拷贝绕过用户空间,显著降低 CPU 占用与上下文切换开销。对高并发网站而言,它不是“锦上添花”,而是应对大量图片、JS、CSS、视频等静态资源请求时的性能刚需。
必须成套启用的三项基础配置
单独写 sendfile on; 几乎无效。真正触发零拷贝需三者协同:
- sendfile on;:激活内核直送能力,跳过用户态缓冲区
- tcp_nopush on;:依赖 sendfile 路径,将响应头与文件数据合并进单个 TCP 报文段,减少小包数量
-
tcp_nodelay off;:关闭 Nagle 算法;若设为
on,会强制立即发包,直接破坏tcp_nopush的攒包逻辑
精准按资源类型启用,避免全局误配
不建议在 http 块盲目开启,应结合 location 做细粒度控制:
- 图片类:
location ~* \.(jpg|png|webp|svg)$中启用,并关闭 gzip(因压缩必须走用户态) - 大文件类(如 MP4、ZIP):
location ~ \.(mp4|zip|iso)$中额外设置sendfile_max_chunk 512k,防止单次传输阻塞事件循环 - 动态接口、代理路径(
proxy_pass)、内容改写(sub_filter)等一律禁用——这些场景 Nginx 自动回退到传统 read/write 模式
配套优化提升整体吞吐稳定性
这些配置不参与零拷贝路径,但能消除瓶颈、释放 sendfile 效能:
-
open_file_cache max=10000 inactive=60s;:缓存文件句柄与元信息,减少重复 open/stat 开销 -
access_log off;:静态资源 location 中关闭访问日志,避免高并发下 I/O 成瓶颈 -
expires 7d;或add_header Cache-Control "public, max-age=604800";:配合浏览器缓存,从源头减少请求数量
验证是否真实生效的关键方法
不能只看配置写了没,要确认系统调用是否被调用:
- 用
strace -p $(pgrep nginx) -e trace=sendfile64观察 worker 进程是否调用该系统调用 - 压测对比:用
wrk对比开启/关闭 sendfile 时 1MB 静态文件的 QPS 与 CPU 使用率 - 检查错误日志:出现
sendfile() failed提示,说明文件路径非本地磁盘(如 NFS、Docker overlayfs)、或响应缺失Content-Length


















