前端资源缓存优化案例:深入探讨 Nginx 配置中的 Cache-Control 头部叠加问题
问题案例:缓存叠加导致的缓存策略不一致
背景
在多层 Nginx 配置下,Cache-Control
头部的配置可能出现 叠加 问题,导致缓存策略不一致。假设我们有两层 Nginx 配置,其中 nginx A
配置了 Cache-Control: no-cache
,而 nginx B
配置了 Cache-Control: public, max-age=86400
。这种情况下,最终返回的 Cache-Control
头部会是两个头部的叠加:
Cache-Control: no-cache, public, max-age=86400
这导致客户端无法根据预期缓存资源,影响性能和资源的更新策略。
排查结果
在 Nginx 中,add_header
指令是 累加式 的,意味着当多个 add_header
被设置时,它们会被合并到响应头部中。如果两层 Nginx 都设置了 Cache-Control
,则返回的响应头会包含两个 Cache-Control
值。
通过以下步骤,我们进行了排查:
查看
nginx A
配置:配置了
Cache-Control: no-cache
。
查看
nginx B
配置:配置了
Cache-Control: public, max-age=86400
。
分析最终响应头:
使用
curl -I
查看响应头,发现最终响应头包含了no-cache, public, max-age=86400
,即两个头部叠加。
结论
在 多层代理配置 中,
Cache-Control
头部会叠加,导致缓存策略混乱。
解决方案
为避免头部叠加,经测试,我们可以在 nginx B
中 location中配置add_header可以完成对http层Cache-Control的重置,并不会叠加,nginx A会返回期望的Cache-Control值
配置修改:
nginx A
配置:
server {listen 80;server_name example.com;location /your-path/ {proxy_pass http://nginxB;}
}
nginx B
配置:
server {listen 80;server_name example.com;location /your-path/ {# 设置 Cache-Control,确保正确的缓存策略add_header Cache-Control "public, max-age=86400";}
}
另外一种方案
nginx A
配置:
google到有提到可以通过proxy_ignore_headers参数让 Nginx A 忽略nginx B Cache-Control 头部,但我实际测下来效果还是二者叠加的结果,原因不详,暂做个记录
server {listen 80;server_name example.com;location /your-path/ {proxy_ignore_headers Cache-Control;add_header Cache-Control "public, max-age=86400";proxy_pass http://nginxB;}
}
效果
无缓存:100~200ms
开启缓存:6-30ms
扩展:前端资源缓存优化
1. 静态资源的长期缓存
对于不会频繁变化的静态资源(如图片、字体、第三方库),可以使用 长期缓存。通过配置较长的 max-age
,浏览器可以缓存这些资源,并减少重复加载:
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|eot)$ {add_header Cache-Control "public, max-age=31536000, immutable";
}
max-age=31536000
:表示资源缓存 1 年。immutable
:表示资源不可更改,浏览器可以安全地长期缓存。
2. 动态资源的缓存
对于经常更新的动态资源(如 HTML 页面和 API 请求),可以使用 短期缓存 或 不缓存,以确保客户端获取到最新内容:
location / {add_header Cache-Control "private, max-age=300";
}
max-age=300
:表示缓存 5 分钟,之后会重新请求服务器。
3. 版本化资源文件
为避免缓存问题,通常会给静态资源文件添加版本号或哈希值,确保每次资源更新时,文件名变化,浏览器能够加载最新版本:
main.abc123.js --> main.js
4. 缓存失效与清理
Etag:基于文件内容生成唯一标识,当文件内容变化时,Etag 也会变化,浏览器会自动请求新资源。
Last-Modified:表示文件的最后修改时间,结合
If-Modified-Since
使用。
location / {add_header Cache-Control "public, max-age=0, must-revalidate";add_header Last-Modified $date_gmt;add_header ETag $request_time;
}
5. 高级缓存优化技巧
CDN 加速:通过 CDN 缓存静态资源,减少原服务器负载,提高响应速度。
缓存穿透与缓存雪崩:使用
Vary
头部和随机过期时间避免这些问题。
add_header Vary Accept-Encoding;
stale-while-revalidate
:缓存过期后,先返回过期内容,后台异步刷新缓存,避免用户等待。
add_header Cache-Control "stale-while-revalidate=60, max-age=86400";
总结
多层 Nginx 配置 ,缓存头部会有叠加问题 。
同时,要积极利用前端资源缓存 + gzip,能显著提升网页加载速度、减少服务器压力