Nginx 缓存
Nginx 的缓存分两层:让浏览器本地缓存静态资源(expires / Cache-Control),以及在 Nginx 上缓存后端响应(proxy_cache)。前者减少重复请求,后者在后端慢或资源紧张时大幅降低源站压力。
第一层:浏览器缓存 expires
给静态资源附带过期时间,浏览器在有效期内直接读本地缓存,不再请求服务器:
server {
location ~* \.(css|js|png|jpg|jpeg|gif|ico|woff2?)$ {
expires 30d; # 30 天过期,自动生成 Expires 与 Cache-Control: max-age=...
}
}
expires 写 -1 表示立即过期(强制每次回源校验)。需要更精确的声明时,可在 location 内用 add_header 显式输出 Cache-Control,例如 add_header Cache-Control "public, max-age=604800";(等价于 7 天,且明确允许公共缓存)。
第二层:proxy_cache 五件套
当后端响应慢或源站流量贵时,让 Nginx 把响应缓存到本地磁盘。核心指令恰好五条:
| 指令 | 作用 |
|---|---|
| proxy_cache_path | 定义缓存目录、目录层级与共享内存区(只能写在 http 层) |
| proxy_cache | 在 server/location 开启缓存并指定 zone 名 |
| proxy_cache_key | 定义缓存键(默认 $scheme$proxy_host$request_uri) |
| proxy_cache_valid | 按状态码设置各响应可缓存的时长 |
| proxy_cache_bypass / proxy_no_cache | 哪些请求穿透后端 / 不写入缓存 |
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m
max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
location / {
proxy_cache mycache; # 启用上面的 zone
proxy_cache_key $scheme$host$request_uri; # 协议+域名+URI 作为键
proxy_cache_valid 200 302 60m; # 200/302 缓存 60 分钟
proxy_cache_valid 404 1m; # 404 仅缓存 1 分钟
proxy_cache_valid any 5m; # 其余状态码 5 分钟
proxy_pass http://127.0.0.1:8080;
}
}
}
参数含义:levels=1:2 表示按两级散列存放文件(避免单目录文件过多);max_size 限制缓存总量,超出后按最少使用淘汰;inactive=60m 表示 60 分钟未被访问即清理。
创建缓存目录并重载:
sudo mkdir -p /var/cache/nginx
sudo nginx -t && sudo systemctl reload nginx
跳过缓存的常见配置
登录后的个性化页面不能缓存,按 Cookie 判断穿透(会话名需与后端一致):
location / {
proxy_cache mycache;
proxy_no_cache $cookie_sessionid; # 带会话 Cookie 的请求不写入缓存
proxy_cache_bypass $cookie_sessionid; # 带会话 Cookie 的请求直接穿透到后端
proxy_pass http://127.0.0.1:8080;
}
验证命中:X-Cache 头
用内置变量 $upstream_cache_status 输出命中状态(HIT 命中 / MISS 未命中 / EXPIRED 过期 / BYPASS 穿透):
location / {
proxy_cache mycache;
add_header X-Cache-Status $upstream_cache_status; # 自定义响应头
proxy_pass http://127.0.0.1:8080;
}
curl -I http://127.0.0.1/ | grep -i x-cache
# 第一次访问:X-Cache-Status: MISS ← 回源并写入缓存
# 第二次访问:X-Cache-Status: HIT ← 命中缓存,未回源
注意:add_header 写在 location 内只对该 location 生效;若后端本身也输出同名头,可先用 proxy_hide_header 隐藏旧值再添加。
适合缓存的内容
- 适合:图片/CSS/JS 等静态资源、新闻详情、更新不频繁且容忍短暂延迟的数据接口。
- 不适合:登录态与隐私页面、库存价格类实时数据、参数带随机数的个性化接口。
小结:浏览器缓存用 expires / Cache-Control 把静态资源"留在客户端",proxy_cache 五件套把后端响应"留在 Nginx"。验证缓存是否生效,一律以响应头中的 X-Cache-Status 为准。