sendfile 在 server 块中配置为 sendfile on; 可使该虚拟主机下所有匹配请求默认启用零拷贝,但仅当请求满足本地静态文件、未代理、未压缩、无内容改写且含 Content-Length 等全部条件时才真正生效;否则自动回退至 read/write 模式。

在 Nginx 的 server 块中,sendfile 可以直接启用或禁用,但要注意:它本身不“属于”虚拟主机逻辑,而是作用于该 server 块内所有匹配的请求——前提是这些请求最终由 Nginx 直接提供静态文件(即未被代理、未压缩、未改写等)。
sendfile 在 server 块中如何配置
sendfile 指令支持出现在 http、server 和 location 三个作用域。在 server 块中设置,表示该虚拟主机下所有未被更细粒度 location 覆盖的请求,默认继承该值。
- 开启:
sendfile on; - 关闭:
sendfile off;
例如:
server {
listen 80;
server_name example.com;
<pre class="brush:php;toolbar:false;">sendfile on; # 对该 server 下所有 location 生效(除非被子 location 覆盖)
location /static/ {
root /var/www;
}
location /api/ {
proxy_pass http://backend;
sendfile off; # 显式关闭,避免与 proxy_pass 冲突
}}
为什么仅在 server 块设 sendfile on 不一定生效
即使你在 server 块写了 sendfile on;,Nginx 仍可能回退到传统读写模式。关键取决于实际响应是否满足零拷贝条件:
- 后端必须是本地文件系统(不支持 NFSv3、某些容器卷、FUSE 等)
- 不能启用
gzip、gunzip或gzip_static - 不能使用
proxy_pass、fastcgi_pass、sub_filter等会介入响应体的指令 - 响应需有明确的
Content-Length(即非 chunked 编码) - 文件不能被重定向或内部跳转到不支持 sendfile 的路径
推荐做法:按资源类型在 location 中精细控制
把 sendfile 放在 server 块容易误伤动态接口。更稳妥的方式是在 location 中按后缀精准启用:
- 对图片、字体、JS/CSS 等静态资源显式开启:
location ~* \.(jpg|jpeg|png|gif|webp|woff2|css|js)$ {
root /var/www/static;
sendfile on;
tcp_nopush on;
tcp_nodelay off;
gzip off;
}
- 对 API 或代理路径默认关闭(或不设,依赖全局默认):
location /v1/ {
proxy_pass http://api_backend;
# 此处 sendfile 自动失效,无需显式关,但可加注释说明
}
验证 sendfile 是否真正生效
光看配置不够,可通过以下方式确认:
- 用
strace -p $(pgrep nginx) -e trace=sendfile观察 worker 进程是否调用sendfile()系统调用 - 对比开启前后,大文件下载的 CPU 使用率和传输延迟变化
- 检查响应头:若出现
Transfer-Encoding: chunked,则 sendfile 必定未启用(因缺少 Content-Length)











