open_file_cache 不缓存目录结构,而是缓存文件元数据和已打开的 fd;其上限由 max、inactive、valid、min_uses、errors 五参数协同控制,并需匹配 worker_rlimit_nofile 和系统级限制。

open_file_cache 本身不缓存“目录结构”,它缓存的是文件的元数据和已打开的文件描述符(fd),比如路径对应的 inode、权限、mtime、是否可读等信息,以及在必要时复用已打开的 fd。所谓“缓存目录结构上限”,实际是指控制整个 open_file_cache 占用的内存与条目数量,防止因缓存膨胀导致内存占用过高或句柄耗尽。
要合理设置上限并防止溢出,关键不是单独配某个“目录结构阈值”,而是通过五项协同参数 + 系统级限制共同约束:
open_file_cache 的容量与淘汰边界必须配齐
只写 open_file_cache on; 或只设 max 是无效的。以下五项必须同时出现在 http { ... } 块中:
open_file_cache max=10000 inactive=60s;
控制缓存总条目数(max)和单个条目存活窗口(inactive)。超出 max 后按 LRU 清理;超过 inactive 时间未被访问即标记为待淘汰。open_file_cache_valid 60s;
每隔 60 秒主动校验缓存项是否仍有效(如文件是否被删、权限是否变更),避免 stale entry 占用资源。open_file_cache_min_uses 2;
同一文件在inactive时间窗口内至少被请求 2 次才进入缓存。防止低频路径(如随机探测的/admin.php.bak)污染缓存。open_file_cache_errors on;
把404、403等失败结果也缓存,避免反复 stat 不存在路径,大幅减少无效系统调用。
缓存上限不能脱离系统资源独立设定
即使 max=10000,若底层无法支撑,缓存会降级或失效:
worker_rlimit_nofile 65535;
放在http或全局块,确保每个 worker 进程能打开足够多的文件描述符(建议 ≥65535)。-
系统级同步调整:
echo 65535 > /proc/sys/fs/file-max ulimit -n 65535 # 启动 Nginx 前生效
-
若启用
open_file_cache_events on;(依赖 inotify),还需:echo 524288 > /proc/sys/fs/inotify/max_user_watches
否则会出现
could not build optimal open_file_cache警告,缓存可能无法正常构建。
避免盲目调高 max 值引发反效果
-
max不是越大越好。例如静态资源共 3000 个文件,设max=20000属于冗余:- 多余条目增加红黑树查找开销
- 更频繁的
valid校验消耗 CPU - 可能触发共享内存锁竞争(尤其 >20000 条目时)
-
推荐基准:
- 小型站点(max=2000
- 中型静态服务(JS/CSS/图片约 5k–10k):
max=8000–12000 - CDN 边缘节点或高频小文件场景:
max=20000–65535,但需验证worker_rlimit_nofile和内存承载能力
监控与验证是否真正生效
重启后检查缓存是否加载成功:
nginx -t && nginx -s reload
观察错误日志是否有:
-
could not build optimal open_file_cache→ inotify 限额不足 -
open() "/xxx" failed (24: Too many open files)→worker_rlimit_nofile或系统 ulimit 不足
运行中可通过 nginx -V 2>&1 | grep -o with-http-cache 确认模块存在,再用 curl -I http://localhost/favicon.ico 多次触发,配合 lsof -p $(pgrep nginx) | wc -l 观察 fd 增长是否明显放缓。
不复杂但容易忽略











