sendfile 与 open_file_cache 必须同时启用才能实现内核零拷贝和元数据零磁盘查询:前者避免用户态拷贝,后者减少 open()/stat() 系统调用;单独启用任一功能均无法突破对应瓶颈。

sendfile 和 open_file_cache 不是互斥功能,而是分工明确、层层递进的协同组合:前者让内核直接传输文件内容,后者让 Nginx 少做甚至不做 open() 和 stat() 系统调用。两者同时启用,才能真正绕过用户态拷贝 + 避开磁盘元数据查询双重瓶颈。
为什么必须一起开
只开 sendfile:Nginx 每次仍要调用 open() 打开文件、stat() 获取大小和 mtime,高频请求下这些系统调用会成为 CPU 和磁盘 I/O 瓶颈;
只开 open_file_cache:文件描述符和元数据虽在内存里,但读取时仍走常规 read() + write() 路径,多一次用户态内存拷贝,浪费 CPU 和带宽。
两者配合,才构成“内核零拷贝 + 元数据零磁盘查询”的完整链路。
配置要点必须对齐
- open_file_cache 必须配齐五项:max、inactive、valid、min_uses、errors,缺一不可;仅写 on 或只设 max=xxx 无效
- sendfile 必须在静态资源 location 中显式开启:sendfile on;(默认 off)
- 建议同步开启 tcp_nopush on;,让 sendfile 发送的数据包不被 Nagle 算法拆分,提升大文件传输效率
- 若使用 alias 或 root 指向真实路径,确保路径合法且文件存在——open_file_cache 只缓存真实文件的 fd 和元数据
系统级配套不能少
这两项功能都依赖底层资源支持:
- worker_rlimit_nofile 至少设为 65535,否则缓存再多 fd 也无法真正打开文件
- 文件系统挂载参数加 noatime,避免每次读取都触发访问时间更新(额外磁盘写入)
- 若启用 open_file_cache_events(推荐),需检查 inotify 句柄上限:/proc/sys/fs/inotify/max_user_watches 建议 ≥ open_file_cache max × 1.5
- 大文件服务场景可进一步关闭日志:access_log off; 和 log_not_found off;,减少 I/O 干扰
典型高效组合示例
适用于多数静态资源节点(如 CDN 回源、SPA 静态托管):
http {
worker_rlimit_nofile 65535;
open_file_cache max=8000 inactive=60s;
open_file_cache_valid 60s;
open_file_cache_min_uses 3;
open_file_cache_errors on;
open_file_cache_events on;
server {
location /static/ {
alias /opt/www/static/;
sendfile on;
tcp_nopush on;
access_log off;
log_not_found off;
}
}
}
该配置下,一个 JS 文件被并发请求 100 次,Nginx 实际只执行 1 次 open()/stat()、1 次 sendfile() 初始化,后续全部走缓存 fd + 内核 DMA 通路。


















