静态资源缓存更新不及时,本质是nginx未感知应更新:浏览器可能因强缓存未发请求,nginx可能命中旧缓存却误判为新,或分布式存储挂载层未向nginx同步文件变更;需分客户端行为、nginx本地缓存逻辑、后端文件系统可见性三层排查。

静态资源缓存更新不及时,不是“Nginx 没删缓存”,而是它根本没意识到该更新——可能浏览器压根没发请求,也可能 Nginx 命中了旧缓存却以为是新的,还可能后端文件已变但挂载层没告诉 Nginx。排查要分三层:客户端行为、Nginx 本地缓存逻辑、后端文件系统可见性。
看浏览器到底有没有发起新请求
打开开发者工具 → Network 标签页 → 刷新页面 → 找到 JS/CSS 等资源 → 看状态码和响应头:
- 如果是 304 Not Modified,说明浏览器发了协商请求,但 Nginx 或后端返回了未修改响应;这时要检查
If-Modified-Since和ETag是否被正确生成或透传 - 如果是 200 但内容仍是旧的,说明请求到了 Nginx,但它返回了缓存副本;需确认是否启用了
proxy_cache或本地文件服务被意外缓存 - 如果压根没出现该资源请求(或显示 from memory cache / disk cache),说明浏览器根本没发请求——问题在
Cache-Control: max-age=31536000或immutable这类强缓存指令上
查 Nginx 是怎么决定缓存还是回源的
在对应 location 块中加一行日志,看清实际执行路径:
-
add_header X-Cache-Status $upstream_cache_status;—— 响应头里会显示HIT、MISS、BYPASS或EXPIRED - 若始终是
HIT,检查proxy_cache_valid是否覆盖了当前状态码(比如只配了200 10m,但后端返回的是200 OK带Cache-Control: private,Nginx 默认不缓存) - 若始终是
MISS,可能是proxy_cache_bypass条件总为真,或proxy_no_cache被设为 1 - 静态文件直出(非 proxy)时,确认没被
expires或add_header Cache-Control错误地长期缓存
验后端文件变更能否被 Nginx 感知到
尤其在 NFS、Ceph 等分布式存储挂载场景下,文件修改后 stat 时间不更新,Nginx 就无法触发基于 mtime 的缓存失效:
- 在 Nginx 服务器上执行:
stat /path/to/your/app.js,改文件后立刻再执行,看 Modify 时间是否秒级变化 - 若不变,检查挂载参数:NFS 应避免
noac或设actimeo=1;禁用soft挂载模式 - 更可靠的做法是绕过 mtime:构建时给文件名加哈希(如
app.a1b2c3.js),HTML 引用新 URL,Nginx 对这类资源配expires 1y; add_header Cache-Control "public, immutable" - HTML 入口文件必须单独处理:设
expires 60s或no-cache,确保用户每次都能拉到含新哈希链接的最新 HTML
快速验证与临时绕过方案
不想改配置时,可用最小干预确认问题边界:
- 加
add_header Cache-Control no-store;到静态资源 location,强制不缓存(仅用于验证) - 临时关闭代理缓存:
proxy_cache off;+proxy_cache_bypass 1;,看是否恢复 - 用
curl -I http://yourdomain.com/app.js绕过浏览器,观察原始响应头和状态码 - 清空 Nginx 缓存目录(如
rm -rf /var/cache/nginx/*)并 reload,排除缓存脏数据干扰











