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-后端缓存分层 当后端响应慢或源站流量贵时,让 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 为准。

笔记加载中…