要让Nginx的sendfile真正发挥零拷贝效能,必须在http块顶层统一配置sendfile on;、tcp_nopush on;、tcp_nodelay off;,并避开gzip、代理指令、内容改写及非本地文件等失效条件。

要让 Nginx 的 sendfile 真正发挥零拷贝效能,不能只写一行 sendfile on;,关键在于成套配置、规避退化路径、并验证运行时是否走通内核直传。
必须同步启用的三个核心指令
这三项缺一不可,且需统一放在 http 块顶层(确保全局生效):
- sendfile on;:激活内核态文件到 socket 的直送能力,跳过用户缓冲区
- tcp_nopush on;:配合 sendfile,让响应头与文件数据尽可能合并进同一个 TCP 报文段,减少小包数量
-
tcp_nodelay off;:关闭 Nagle 算法;若设为
on,会强制立即发包,直接破坏tcp_nopush的攒包逻辑
必须避开的失效条件
只要出现以下任一情况,Nginx 会自动回退到低效的 read()+write() 路径:
- 启用了
gzip on、gunzip on或gzip_static on(压缩/解压必须在用户态完成) - 使用了
proxy_pass、fastcgi_pass、grpc_pass等代理指令 - 配置了
sub_filter、add_before_body等内容改写功能 - 文件位于 NFS、FUSE、容器卷等不支持
sendfile()系统调用的文件系统上 - 响应未带
Content-Length(如 chunked 编码或动态生成)
推荐补充的协同优化项
这些不改变零拷贝路径,但能显著提升稳定性与吞吐量:
- sendfile_max_chunk 512k;:限制单次 sendfile 传输量,防止单个大文件阻塞事件循环(对图片、视频首段加载更友好)
-
open_file_cache max=10000 inactive=60s;:缓存文件句柄和元信息,避免重复
open()和stat()开销 - access_log off;:纯静态资源 location 中关闭访问日志,大幅减轻高并发下的 I/O 与 CPU 压力
-
gzip_static on; gzip off;:提供预压缩的
.gz文件(如style.css.gz),仍可走 sendfile,兼顾压缩与零拷贝
如何验证是否真正生效
不能只看配置语法正确,要确认运行时实际走的是零拷贝路径:
- 用
strace -p $(pgrep nginx | head -1) -e trace=sendfile64,read,write观察 worker 进程:应高频触发sendfile64,几乎不出现read和write - 高并发压测下对比 CPU 使用率:开启后系统态(
sy)占比应明显下降,QPS 提升通常达 20%–50% - 检查文件本身:普通 ext4/xfs 本地文件、大小 ≥ 4KB、未被其他进程加锁、未用
O_DIRECT打开











