{"msg":"操作成功","code":200,"data":{"createBy":"admin","createTime":"2025-06-04 11:23:46","updateBy":"admin","updateTime":"2025-06-24 11:27:11","remark":null,"id":114,"articleTitle":"Nginx（七）缓存功能","articleUrl":"nginx_cache","articleThumbnail":"https://www.asumimoe.com/imgfiles/20250618/4b57c2e46f8949e5a30d4e2e9e8a8fd5.png","articleFlag":"1","draftStatus":"1","reprintStatement":"0","articleSummary":"Nginx 的缓存机制主要基于HTTP 协议的缓存语义和反向代理架构，通常用于加速静态内容（如图片、CSS、JS 文件）和部分动态内容的访问。","articleContent":"缓存能够存储请求的响应结果，以供未来再次使用，进而加速内容的提供。内容缓存可以缓存完整的响应，减少上游服务器的负载，避免了每次都为相同的请求重新运行计算和查询的麻烦。缓存可以提高性能并减少负载，这意味着您可以用更少的资源更快地提供服务。缓存服务器在战略位置上的扩展和分布会对用户体验产生巨大影响。最好将内容托管在靠近消费者的地方，这有助于释放最高性能。您还可以在靠近用户的地方缓存内容，内容交付网络（CDN）就采用了这种模式。NGINX 允许您在放置NGINX 服务器的任何地方缓存内容，从而有效创建自己的 CDN。借助 NGINX 缓存，您还可以在上游（upstream）发生故障时被动地缓存并提供缓存的响应。缓存功能仅在 http 上下文中可用。\n\n## Nginx 缓存的基本概念与工作原理\n\nNginx 的缓存机制主要基于 **HTTP 协议的缓存语义** 和 **反向代理架构**，通常用于加速静态内容（如图片、CSS、JS 文件）和部分动态内容的访问。它的核心思想是：\n\n- **代理请求**：Nginx 作为反向代理服务器接收客户端请求。\n- **判断是否命中缓存**：\n  - 如果缓存中存在有效响应，则直接返回；\n  - 如果不存在或已过期，则向后端服务器发起请求获取新内容，并将结果缓存下来供后续请求使用。\n- **支持缓存清除**：通过第三方模块或手动方式可清理特定缓存项。\n\n## 启用 Nginx 缓存的完整配置步骤\n\n### 1. 定义缓存路径（必须放在 `http` 块中）\n\n```nginx\nhttp {\n    proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;\n}\n```\n\n| 参数                     | 含义                                                    |\n| ------------------------ | ------------------------------------------------------- |\n| `proxy_cache_path`       | 指定缓存文件存储的目录                                  |\n| `levels=1:2`             | 设置缓存目录层级结构（最多3层），避免单个目录下文件过多 |\n| `keys_zone=my_cache:10m` | 定义共享内存区名称及大小，用于存放缓存键和元数据        |\n| `max_size=10g`           | 缓存最大占用磁盘空间，超过时按 LRU 算法删除             |\n| `inactive=60m`           | 若缓存未被访问超过此时间则自动删除                      |\n| `use_temp_path=off`      | 避免使用临时路径，减少磁盘 I/O                          |\n\n### 2. 在 `location` 或 `server` 中启用缓存\n\n```nginx\nlocation /static/ {\n    proxy_cache my_cache;\n    proxy_pass http://backend_server;\n}\n```\n\n你也可以根据不同的 URL 路径设置不同的缓存策略。\n\n## 缓存行为的精细控制\n\n### 1. 设置缓存有效期（推荐）\n\n```nginx\nproxy_cache_valid 200 302 10m;   # 对状态码 200 和 302 的响应缓存 10 分钟\nproxy_cache_valid 404 1m;        # 对 404 页面仅缓存 1 分钟\nproxy_cache_valid any 5m;        # 其他所有响应缓存 5 分钟\n```\n\n> ⚠️ 注意：如果后端设置了 `Cache-Control` 或 `Expires` 头，Nginx 默认会遵循这些值。你可以用 `proxy_ignore_headers Cache-Control;` 来忽略它们并强制使用自己的缓存策略。\n\n### 2. 忽略某些头信息以提高缓存命中率\n\n```nginx\nproxy_ignore_headers Cache-Control Set-Cookie;\n```\n\n这可以防止因 Cookie 或 Cache-Control 不一致导致缓存未命中。\n\n### 3. 自定义缓存键（Key）\n\n默认情况下，Nginx 使用 `host + uri + args` 作为缓存键。可以通过以下方式自定义：\n\n```nginx\nproxy_cache_key \"$host$request_method$uri$is_args$args\";\nproxy_cache_key \"$host$request_uri $cookie_user\";\n```\n\nproxy_cache_key 的默认配置是“$scheme$proxy_host$request_uri”，该配置适用于大多数用例。使用的变量包括 scheme、HTTP 或 HTTPS、proxy_host（发送请求）以及请求 URI。总之，这反映了 NGINX 将请求代理到哪个 URL。您可能会发现，还有许多其他因素定义了每个应用的唯一请求，比如请求参数、请求头、会话标识符等等，您希望为这些因素创建自己的哈希键。\n\n选择一个好的哈希键非常重要，其中离不开对应用的了解。为静态内容选择缓存键通常非常简单，只需使用主机名和 URI 便可。但如果是为相当动态的内容（例如仪表盘应用的页面）选择缓存键，就要求对用户与应用的交互方式以及用户体验之间的差异程度有着更深刻的认识。出于安全考虑，您可能不希望在没有完全了解上下文的情况下就将用户的缓存数据展示给其他用户。proxy_cache_key 指令将字符串配置为缓存键的哈希值，该指令可以在 http、server 和 location 代码块中进行设置，从而灵活控制请求的缓存方式。\n\n### 4. 缓存绕过条件（Bypass）\n\n你可以设置某些条件下跳过缓存，比如有特殊参数或 Cookie：\n\n```nginx\nset $no_cache 0;\n\nif ($request_method = POST) {\n    set $no_cache 1;\n}\n\nif ($query_string ~* \"nocache\") {\n    set $no_cache 1;\n}\n\nproxy_cache_bypass $no_cache;\nproxy_no_cache $no_cache;\n```\n\n## 缓存清理（Purge）\n\nNginx 原生不支持缓存清理，但可以通过安装 **第三方模块 ngx_cache_purge** 实现：\n\n### 示例配置：\n\n```nginx\nlocation ~ /purge(/.*) {\n    allow 127.0.0.1;     # 限制只有本地可以执行 purge\n    deny all;\n    proxy_cache_purge my_cache \"$host$1$is_args$args\";\n}\n```\n\n### 使用方式：\n\n发送一个请求到 `/purge/xxx` 即可清除对应缓存：\n\n```bash\ncurl -X PURGE http://yourdomain.com/purge/static/image.png\n```\n\n---\n\n## 监控缓存命中情况\n\n可以在日志中记录缓存状态：\n\n```nginx\nlog_format cache '$remote_addr - $remote_user [$time_local] '\n                 '\"$request\" $status $body_bytes_sent '\n                 '\"$http_referer\" \"$http_user_agent\" '\n                 'cache_status: $upstream_cache_status';\n\naccess_log /var/log/nginx/access.log cache;\n```\n\n其中 `$upstream_cache_status` 可能的值包括：\n\n- `MISS`：未命中，从后端取回\n- `HIT`：命中缓存\n- `EXPIRED`：缓存过期，正在重建\n- `STALE`：缓存过期但仍在使用（需启用 `proxy_cache_use_stale`）\n- `UPDATING`：正在更新缓存\n- `REVALIDATED`：经过验证后继续使用缓存\n\n## 性能优化建议\n\n| 优化点                          | 说明                                          |\n| ------------------------------- | --------------------------------------------- |\n| 使用 SSD 存储缓存               | 提高读写速度                                  |\n| 分配足够大的内存区（keys_zone） | 避免频繁磁盘查找                              |\n| 控制缓存目录层级                | 推荐使用 `levels=1:2`，平衡访问效率与管理难度 |\n| 合理设置 `inactive` 时间        | 避免缓存堆积                                  |\n| 启用 `proxy_cache_min_uses`     | 设置某个资源最少被访问几次才缓存              |\n| 启用 `proxy_cache_lock`         | 防止多个相同请求同时穿透到后端                |\n| 启用 `proxy_cache_use_stale`    | 当后端不可用时使用旧缓存响应用户              |\n\n示例：\n\n```nginx\nproxy_cache_lock on;\nproxy_cache_min_uses 2;\nproxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;\n```\n\n## 常见问题排查技巧\n\n| 问题             | 解决方案                                               |\n| ---------------- | ------------------------------------------------------ |\n| 缓存命中率低     | 查看 `$upstream_cache_status` 日志，检查缓存键是否唯一 |\n| 缓存未生效       | 检查是否有 `Set-Cookie` 或 `Cache-Control: no-cache`   |\n| 缓存目录无法写入 | 检查 nginx 用户对缓存目录的权限                        |\n| 清理缓存失败     | 检查是否安装了 `ngx_cache_purge` 模块                  |\n| 缓存文件过大     | 适当调整 `max_size` 和 `inactive` 参数                 |\n\n#### 参考资料\n\n- [Nginx 官方文档](https://nginx.org/en/docs/)","categoryId":12,"viewCount":114,"categoryName":"Nginx","author":"球接子","authorAvatar":null,"tagIds":[13,14],"tagNames":["Nginx","中间件"]}}