根本原因是 open_file_cache 缓存文件元数据(如 mtime),导致 Nginx 误判 HTML 未变更而复用旧内容;sendfile 仅放大该问题。应禁用 location 中的 open_file_cache 或调小 inactive/valid 时间,并配合浏览器缓存控制。

修改 HTML 文件后刷新页面仍显示旧内容,sendfile 配置确实是常见诱因之一,但它只是“表面现象”,背后实际涉及 Nginx 的文件元数据缓存机制(open_file_cache)与内核级零拷贝传输的协同行为。开启 sendfile on 本身不会导致内容不更新,但会放大 open_file_cache 对文件修改时间(mtime)和大小等元数据的缓存效应——Nginx 可能仍认为“文件没变”,于是跳过重新读取磁盘,直接复用旧的内核页缓存或已打开的文件句柄。
确认是否是 sendfile + open_file_cache 共同影响
Nginx 默认启用 sendfile on,同时也默认启用 open_file_cache(即使配置中未显式写出)。后者才是真正“记住了旧文件状态”的组件。当 HTML 文件被覆盖(如 cp new.html index.html),若 open_file_cache 尚未失效,Nginx 仍会按缓存中的旧 mtime 判断文件未变更,进而跳过重新 stat 和 read 操作。
- 检查当前是否启用了
open_file_cache:在nginx.conf的http或server块中查找类似open_file_cache max=1000 inactive=20s;的配置 - 临时禁用它可快速验证:注释或删除该行,执行
nginx -s reload - 若此时修改 HTML 并刷新立即生效,说明问题根源在此,而非 sendfile 本身
sendfile 关闭不是推荐解法
把 sendfile off 确实能绕过内核零拷贝路径,迫使 Nginx 经由用户态 buffer 读取文件,从而“被动”触发对文件真实状态的重新检查。但这会带来性能损耗,尤其在高并发静态资源场景下。
- 仅在调试阶段临时使用,不建议长期关闭
- 关闭后仍需配合
open_file_cache off或调小inactive时间,否则仍可能卡在元数据缓存层 - 更合理的做法是保留
sendfile on,专注优化open_file_cache的刷新策略
真正有效的配置调整方案
目标是让 Nginx 在文件变更后尽快感知并重载内容,同时不牺牲性能:
立即学习“前端免费学习笔记(深入)”;
- 显式启用并收紧
open_file_cache:例如open_file_cache max=1000 inactive=5s; open_file_cache_valid 5s; open_file_cache_min_uses 1; - 确保
open_file_cache_errors on;,避免因权限或路径错误导致缓存永久失效 - HTML 类文件建议禁用
open_file_cache:在对应location块中加open_file_cache off;,因为它们变更频繁、体积小,无需缓存句柄 - 发布时执行
nginx -s reload(非 restart),可清空open_file_cache内存项
别忘了浏览器那一端
即使 Nginx 立即读取了新文件,用户看到的仍是旧内容,大概率是因为浏览器强缓存了 HTML:
- 检查响应头是否有
Cache-Control: max-age=3600或类似长时效设置 - 开发/预发环境建议设为
Cache-Control: no-cache, must-revalidate - 上线时对 HTML 使用版本化路径(如
/index.v2.html)或添加时间戳参数(?t=202609160330),彻底规避缓存复用



















