启用sendfile零拷贝需在http块统一配置sendfile on、tcp_nopush on、tcp_nodelay off,并避开gzip、sub_filter及非本地文件等失效条件。

在 Nginx 全局(http 块)中配置 sendfile,是启用内核级零拷贝传输静态文件最直接有效的方式。关键不是简单打开开关,而是让 sendfile 与配套机制协同工作,同时避开常见失效条件。
必须启用的核心指令
以下三项需统一写在 http 块顶层,确保对所有 server 和 location 生效:
-
sendfile on;—— 启用零拷贝基础能力,跳过用户态内存拷贝 -
tcp_nopush on;—— 配合sendfile,让内核等到响应数据填满 TCP 缓冲区再发包,减少小包数量 -
tcp_nodelay off;—— 关闭 Nagle 算法,避免与tcp_nopush冲突;二者不可同时为on
推荐补充的性能优化项
这些设置不改变零拷贝路径,但能提升整体静态资源分发稳定性与吞吐:
-
sendfile_max_chunk 512k;—— 限制单次sendfile调用的数据量,防止大文件传输阻塞事件循环;512KB 是兼顾平均图片/JS/CSS 大小的稳妥值 -
open_file_cache max=10000 inactive=60s;—— 缓存文件句柄和元信息,降低重复open()开销 -
access_log off;—— 对纯静态资源服务,关闭访问日志可显著减轻 I/O 和 CPU 压力(若需日志,建议异步写入或单独归档)
务必规避的冲突配置
以下任一配置都会导致 sendfile 自动失效,回退到传统 read()+write() 流程:
-
gzip on;或gunzip on;—— 压缩/解压必须在用户态完成,强制绕过零拷贝 -
sub_filter、add_before_body、add_after_body等内容改写指令 —— 触发缓冲与重写逻辑 - 使用
alias指向非真实磁盘路径(如符号链接指向容器卷、NFS 或 FUSE 文件系统)—— 部分远程文件系统不支持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打开










