sendfile64是Nginx在64位Linux系统上自动启用的64位零拷贝机制,用于高效传输大于2GB文件;需满足内核≥2.6.11、Nginx含http_sendfile_module、配置sendfile on及tcp_nopush on,并避开Range/etag等限制场景。

在 Nginx 中,sendfile 是一个内核级的高效文件传输机制,能显著降低大文件(如视频、ISO 镜像等)下载时的 CPU 和内存开销。所谓 “sendfile64”,并非 Nginx 的独立配置项,而是指 Nginx 在启用 sendfile on 且运行于支持 sendfile64() 系统调用的 64 位操作系统(如 Linux 2.6+)上时,自动使用 64 位版本的系统调用来处理大于 2GB 的文件。
确认系统和 Nginx 支持 sendfile64
Nginx 自 0.8.15 起默认启用对大文件的 sendfile64 支持,前提是:
- 操作系统为 64 位 Linux(如 CentOS 7+/Ubuntu 16.04+),内核 ≥ 2.6.11(已原生支持
sendfile64) - Nginx 编译时未禁用
--without-http_sendfile_module - 文件系统支持大文件(ext4/xfs 等,默认支持)
可通过命令验证:nginx -V 2>&1 | grep -o with-http_sendfile_module,有输出即表示模块已启用。
在 http 段正确开启 sendfile
只需在 http{...} 块中添加以下两行即可启用并优化 sendfile 行为:
sendfile on; tcp_nopush on;
说明:
-
sendfile on:启用内核零拷贝传输;Nginx 自动调用sendfile64()处理 >2GB 文件,无需额外配置 -
tcp_nopush on:配合sendfile,让 Nginx 尽可能把响应头和文件数据合并进一个 TCP 包发送,减少网络包数量
注意 sendfile 的限制与绕过场景
sendfile 虽高效,但有天然限制:
- 不支持带条件的响应(如
If-Modified-Since或Range请求中的部分下载),此时 Nginx 会自动退回到用户态读写(read()+write()) - 无法处理需要动态修改内容的场景(如
add_header后需重写响应体) - 某些代理或安全模块(如某些 WAF)可能强制关闭
sendfile
若需确保大文件始终走零拷贝,应避免在 location 中设置 etag off、expires 冲突,或慎用 sub_filter 等内容改写指令。
验证大文件是否走 sendfile64
可通过内核跟踪简单确认:
- 运行
sudo strace -p $(pgrep nginx) -e trace=sendfile64 -f 2>&1 | grep sendfile64 - 用浏览器或
wget请求一个 >3GB 的静态文件,若看到类似sendfile64(12, 15, [0], 3221225472) = 3221225472的日志,说明已生效
也可观察 Nginx 日志中该请求的 $sent_http_content_length 与实际文件大小一致,且响应时间低、CPU 占用平稳,是间接佐证。










