启用 sendfile 可显著提升静态文件传输效率,因其通过内核直接将磁盘文件发送至网络套接字,避免用户态拷贝与上下文切换;需配置 sendfile on、tcp_nopush on,并注意仅对真实磁盘文件生效且与 gzip 冲突。

在 Nginx 的 http 块中启用 sendfile,能显著提升静态文件(如图片、CSS、JS)的传输效率,尤其在高并发或大文件场景下效果明显。
sendfile 是什么?为什么能提速?
sendfile 是 Linux 内核提供的系统调用,允许 Nginx 直接将文件从磁盘读取并发送到网络套接字,无需经过用户空间缓冲区。相比传统 read/write 方式,它减少了数据在内核态和用户态之间的多次拷贝与上下文切换,降低 CPU 和内存开销。
如何正确开启 sendfile
在 http 块(或 server、location 块)中添加以下配置:
-
sendfile on;—— 启用 sendfile 机制 -
tcp_nopush on;—— 配合使用,让 Nginx 在发送响应头后,尽可能把整个文件一次性推送到 TCP 缓冲区(避免小包发送) -
tcp_nodelay on;—— 通常用于长连接或实时交互,在 sendfile 场景下非必需,但不影响;若已启用tcp_nopush,该指令对静态文件影响不大
注意事项与常见误区
启用 sendfile 并不总是“开箱即用”,需注意以下几点:
- 仅对真实磁盘文件生效(如
root指向的本地路径),不适用于代理响应、动态内容(PHP/Go 等后端返回)、或通过alias映射的非标准路径(某些旧版本有兼容问题) - 若启用了
gzip或gunzip模块,Nginx 会自动禁用 sendfile,因为压缩/解压必须经过用户空间处理 - 在使用 X-Accel-Redirect 或类似内部重定向时,确保响应体来自真实文件且未被修改,否则 sendfile 可能被跳过
- 某些容器环境(如 Docker 默认存储驱动)或 NFS 文件系统可能不完全支持 sendfile,可结合
strace或日志中的sendfile() failed判断是否实际生效
验证是否生效
可通过以下方式确认 sendfile 是否被调用:
- 检查 Nginx 错误日志是否有
sendfile() failed类报错 - 用
strace -p $(pgrep nginx) -e trace=sendfile64观察 worker 进程是否调用该系统调用 - 对比开启/关闭 sendfile 时的 QPS 和 CPU 使用率(例如用
ab或wrk压测一个 1MB 静态文件)

















