开启sendfile能显著降低cpu和内存开销,因其绕过用户态搬运,由内核直接完成磁盘到网络传输:传统read/write需4次拷贝+4次上下文切换,sendfile仅2次内核态拷贝,减少系统调用与中断,高并发下cpu使用率可降30%–60%,尤其适用于1mb+静态文件。

开启 sendfile 能显著降低 Nginx 服务静态资源时的 CPU 和内存开销,核心在于绕过用户态数据搬运,让内核直接完成磁盘到网络的传输。
为什么能降低 CPU 占用
传统 read/write 方式需 4 次数据拷贝 + 4 次上下文切换:磁盘→内核缓冲区→用户空间→socket 缓冲区→网卡。而 sendfile 仅需 2 次拷贝(磁盘→内核缓冲区→网卡)且全程在内核态完成,CPU 不再参与中间搬运。
- 高并发下,CPU 使用率可下降 30%–60%,尤其在传输 1MB+ 图片、JS、视频等大文件时效果突出
- 避免用户空间分配和管理缓冲区内存,减少内存压力与 GC 开销(对带 Lua 或 JS 引擎的定制版 Nginx 更明显)
- 系统调用次数减少,中断频率下降,提升整体调度效率
哪些配置会抵消 sendfile 的收益
即使写上 sendfile on;,以下操作也会导致 Nginx 自动回退到 read/write 模式,CPU 开销重新升高:
- 启用
gzip on或gunzip on:压缩必须进用户态处理,彻底阻断零拷贝路径 - 使用
etag on、expires或add_header动态计算响应头:触发用户态介入 - 客户端发起 Range 请求(如视频拖拽):Nginx 需切片读取,无法整块 sendfile
- 静态文件位于 NFS/CIFS 等不支持 sendfile 的远程挂载点
- location 中混用
proxy_pass、sub_filter或X-Accel-Redirect且目标非本地真实文件
如何验证资源利用率是否真正改善
不能只看配置是否开启,要观察运行时行为:
- 用
strace -p $(pgrep nginx) -e trace=sendfile64检查 worker 进程是否持续调用该系统调用 - 压测同一静态文件(如 2MB CSS),对比开启/关闭 sendfile 时的
pidstat -u 1输出:关注 %usr 和 %sys 变化 - 监控 QPS 提升幅度——若 CPU 下降但 QPS 几乎不变,说明瓶颈已转移至磁盘 I/O 或网络带宽
配套调优才能守住低资源占用
单独开 sendfile 不够,还需收敛其他用户态干扰:
- 搭配
tcp_nopush on:让 sendfile 数据尽量填满 TCP 包,减少小包数量和协议栈开销 - 禁用运行时压缩:
gzip off,改用gzip_static on返回预压缩 .gz 文件 - 启用
open_file_cache:缓存文件句柄与元数据,避免高并发下频繁 open/stat 触发用户态系统调用 - 精简 access_log:关闭日志或去除
$body_bytes_sent类需等待响应结束的变量,防止日志阻塞 worker











