一、静态文件缓存
静态文件缓存通常通过 expires 和 cache-control 头来实现,让浏览器或 CDN 缓存静态资源。
location /static/ {
expires 30d; # 浏览器缓存时间
add_header Cache-Control public; # 设置缓存策略
}
-
expires:设置资源在浏览器中的缓存时间,如30d表示 30 天。 -
add_header Cache-Control public:设置 HTTP 头,允许任何缓存服务器缓存资源。
二、反向代理缓存(Proxy Cache)
Nginx 可以作为反向代理,对后端服务器的响应进行缓存,大幅提升性能。
1. 启用缓存
# 定义缓存路径和参数
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:50m inactive=1d max_size=10g;
server {
location / {
proxy_pass http://backend;
proxy_cache my_cache; # 使用名为 my_cache 的缓存区
proxy_cache_valid 200 302 10m; # 200/302 响应缓存 10 分钟
proxy_cache_valid 404 1m; # 404 响应缓存 1 分钟
proxy_cache_key "$scheme$request_method$host$request_uri"; # 缓存键
add_header X-Cache-Status $upstream_cache_status; # 缓存命中状态
}
}
参数详解
-
proxy_cache_path:定义缓存目录、层级、缓存区名、最大大小等。-
/data/nginx/cache:缓存文件存放路径。 -
levels=1:2:缓存文件目录层级(防止单目录文件过多)。 -
keys_zone=my_cache:50m:分配 50MB 内存给缓存区 my_cache。 -
inactive=1d:缓存内容 1 天无访问则自动清除。 -
max_size=10g:最大缓存空间 10GB。
-
-
proxy_cache:指定使用哪个缓存区。 -
proxy_cache_valid:指定不同响应码的缓存时间。 -
proxy_cache_key:定义缓存的唯一键,常用$scheme$request_method$host$request_uri。 -
add_header X-Cache-Status $upstream_cache_status:返回缓存命中状态(MISS, HIT, EXPIRED 等)。
2. 控制缓存行为
-
proxy_cache_bypass $cookie_nocache $arg_nocache;- 根据条件跳过缓存(如参数、Cookie 等)。
-
proxy_no_cache $cookie_nocache $arg_nocache;- 不缓存特定请求。
3. 清理缓存
Nginx 自身没有直接的缓存清理命令,通常通过删除缓存文件或使用第三方工具(如 nginx-cache-purge)实现。
三、常用优化建议
- 合理设置缓存时间:不同资源设置不同的缓存时间,动态页面短,静态资源长。
- 缓存键设计:确保缓存键能区分不同用户、参数等,避免缓存污染。
- 定期清理缓存:避免磁盘空间被缓存文件占满。
-
结合后端缓存头:如后端设置
Cache-Control: no-cache,Nginx 可据此不缓存。
四、完整示例
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_zone:100m inactive=1h max_size=1g;
server {
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_cache cache_zone;
proxy_cache_valid 200 5m;
proxy_cache_valid 404 1m;
proxy_cache_key "$scheme$host$request_uri";
add_header X-Cache $upstream_cache_status;
proxy_cache_bypass $cookie_nocache $arg_nocache;
proxy_no_cache $cookie_nocache $arg_nocache;
}
}
五、常见问题
-
缓存不生效?
- 检查
proxy_cache_path和proxy_cache匹配。 - 检查缓存键是否唯一。
- 检查后端是否返回了
Cache-Control: no-cache或private。
- 检查
-
如何刷新缓存?
- 删除缓存目录下对应文件。
- 使用第三方 purge 模块。
六、缓存控制相关指令详解
1. proxy_cache_methods
指定哪些 HTTP 方法的请求可以被缓存,默认只缓存 GET 和 HEAD。
proxy_cache_methods GET HEAD POST;
一般不建议缓存 POST 请求,除非业务场景特殊。
2. proxy_cache_min_uses
设置某个资源被访问多少次后才进行缓存,防止缓存冷门资源。
proxy_cache_min_uses 3; # 第三次访问后才缓存
3. proxy_cache_lock
防止高并发下同一个资源被重复请求时,后端压力过大。第一个请求未完成时,后续请求等待第一个请求结果。
proxy_cache_lock on;
proxy_cache_lock_timeout 5s; # 最多等待 5 秒
4. proxy_cache_use_stale
后端服务器不可用时,是否使用过期缓存内容。
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
这样可以提升高可用性,后端宕机时用户还能看到旧内容。
5. proxy_ignore_headers
忽略后端返回的某些头部(如 Cache-Control),强制缓存。
proxy_ignore_headers "Cache-Control" "Expires";
某些后端总返回 no-cache,可以用此指令强制缓存。
七、缓存清理方案
1. 手动清理
直接删除缓存目录下的文件。
适合小规模、临时清理。
rm -rf /data/nginx/cache/*
2. nginx-cache-purge 模块
支持 HTTP 接口清理缓存。配置如下:
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge my_cache $scheme$request_method$host$1;
}
- 访问
/purge/xxx即可清理缓存。 - 需编译 Nginx 时加上该模块。
3. 定期清理
结合 Linux 定时任务(crontab)自动清理过期或无用缓存文件。
八、缓存命中分析与调试
1. 添加缓存命中头
add_header X-Cache-Status $upstream_cache_status;
-
MISS:未命中,已缓存 -
HIT:命中缓存 -
EXPIRED:缓存过期 -
BYPASS:未缓存(如被 bypass)
2. 日志分析
可以在 a***ess_log 加入 $upstream_cache_status 字段,便于后期统计分析。
log_format cachelog '$remote_addr - $host $request $status $upstream_cache_status';
a***ess_log /var/log/nginx/cache_a***ess.log cachelog;
九、与后端协作
-
后端控制缓存
后端可通过响应头控制 Nginx 缓存行为:-
Cache-Control: no-cache或private:不缓存 -
Cache-Control: max-age=60:缓存 60 秒
-
-
ETag/Last-Modified
Nginx 支持 If-Modified-Since/If-None-Match 协议,减少流量。
十、常见业务场景举例
1. API 接口缓存
- 对 GET 请求缓存 3 分钟,POST 请求不缓存。
- 用户参数如 token、session 不纳入缓存键。
2. 静态资源 CDN 缓存
- 图片、JS、CSS 缓存 30 天。
- 文件更新时自动刷新缓存。
3. 多级缓存
- 前端 CDN + Nginx 缓存 + 后端缓存(如 Redis),分层加速。
十一、配置模板(综合示例)
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=site_cache:200m inactive=12h max_size=5g;
server {
location /api/ {
proxy_pass http://backend;
proxy_cache site_cache;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_valid 200 301 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_min_uses 2;
proxy_cache_methods GET HEAD;
proxy_cache_lock on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
proxy_cache_bypass $cookie_nocache $arg_nocache;
proxy_no_cache $cookie_nocache $arg_nocache;
}
}
十二、高级应用技巧
1. 分用户/分参数缓存
有些接口需要根据用户身份或参数做缓存隔离,避免缓存串号。可以调整 proxy_cache_key:
# 例如按用户ID区分缓存
proxy_cache_key "$scheme$host$request_uri|$cookie_userid";
这样每个用户都会有独立缓存,适合个性化内容。
如果只对部分参数敏感,可以用 $arg_xxx 变量拼接缓存键。
2. 动态控制缓存(变量控制)
Nginx 支持用变量动态决定是否缓存:
set $skip_cache 0;
if ($request_method = POST) {
set $skip_cache 1;
}
if ($arg_nocache = 1) {
set $skip_cache 1;
}
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
这样可以灵活控制哪些请求缓存、哪些不缓存。
3. 缓存预热(Cache Warm-up)
上线新服务或重启后,缓存是冷的。可以用脚本提前批量请求热门资源,把缓存“预热”好,避免用户首次访问慢。
4. 多级缓存策略
前端 CDN 缓存 + Nginx 缓存 + 后端缓存(如 Redis/Memcached),实现多级加速和分流。
十三、缓存常见问题排查
1. 缓存未命中?
- 检查
proxy_cache_path和proxy_cache是否对应。 - 检查
proxy_cache_key是否唯一且合理,有无参数遗漏。 - 检查
proxy_cache_bypass、proxy_no_cache是否被触发。 - 检查后端返回的
Cache-Control、Set-Cookie是否禁止缓存。 - 查看
X-Cache-Status头部,区分MISS、BYPASS、EXPIRED等状态。
2. 缓存错乱/串号?
- 检查缓存键是否包含所有影响内容的参数(如用户ID、设备类型等)。
- 检查是否有 Cookie、Header 等影响内容但未纳入缓存键。
3. 缓存空间不足/缓存文件太多?
- 调整
max_size、inactive参数。 - 定期清理缓存目录。
- 检查磁盘空间,防止 Nginx 写入失败。
4. 缓存更新后用户还看到旧内容?
- 检查缓存清理是否生效。
- 检查 CDN 是否还缓存了旧内容。
- 检查浏览器缓存是否未刷新。
十四、缓存与安全注意事项
-
敏感信息不缓存
- 登录态、个人数据、支付信息等接口,务必设置
proxy_no_cache,防止缓存泄露。 - 后端返回
Cache-Control: private, no-store,Nginx 配合proxy_no_cache。
- 登录态、个人数据、支付信息等接口,务必设置
-
防止缓存污染
- 缓存键要包含所有影响内容的参数,防止 A 用户看到 B 用户内容。
- 不要缓存带有用户凭证的请求(如带 Cookie、Token)。
-
防止缓存穿透
- 对 404/500 等错误响应设置较短缓存时间,避免恶意请求拖垮后端。
十五、典型场景配置模板
1. 防止用户信息串号
proxy_cache_key "$scheme$host$request_uri|$cookie_sessionid";
2. 仅缓存 GET 请求,POST 不缓存
proxy_cache_methods GET HEAD;
if ($request_method != GET) {
set $skip_cache 1;
}
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
3. 缓存 404/500 响应
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid 500 502 503 504 30s;
十六、缓存调优建议
-
合理分配缓存空间,结合业务流量和磁盘容量设置
max_size。 -
活跃数据优先缓存,用
inactive控制冷数据自动淘汰。 -
日志监控,关注
X-Cache-Status、磁盘空间、命中率等指标。 -
高可用设计,启用
proxy_cache_use_stale,应对后端故障。