> For the complete documentation index, see [llms.txt](https://www.axisnow.io/zh/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.axisnow.io/zh/docs/edge/policies/cache/how-it-works.md).

# 工作原理

缓存的命中流程与状态含义以及节点存储方式

## 命中流程 <a href="#request-flow" id="request-flow"></a>

命中「可缓存」规则后，边缘按规则生成缓存 Key 查找本节点的缓存：

* 有新鲜副本，直接应答，状态 `HIT`。
* 副本已过期，回源校验：副本带 `Last-Modified` 或 `ETag` 时发条件请求，源站返回 304 则续期并用原副本应答，状态 `REVALIDATED`；返回新内容则替换副本，状态 `EXPIRED`。副本没有这两个头、或源站不处理条件请求时，每次过期都重新下载完整内容。过期期间的请求等待回源完成，不先用旧副本应答。
* 没有副本，回源并按[缓存时长](/zh/docs/edge/policies/cache/configuration.md#ttl)的规则决定是否写入，状态 `MISS`。算出不缓存的响应每次都是 `MISS`，没有单独的状态。

同一 Key 的并发未命中只放一个请求回源，其余最多等待 3 秒后各自回源、不写缓存。源站出错或超时时不会用过期副本兜底。

命中「绕过缓存」规则的请求直接回源，状态 `BYPASS`。

## 缓存状态 <a href="#cache-status" id="cache-status"></a>

命中可缓存规则的响应带三个头，用于排错；绕过规则的响应只带 `X-Cache: BYPASS`。

<table data-search="false"><thead><tr><th width="160">响应头</th><th>含义</th></tr></thead><tbody><tr><td><code>X-Cache</code></td><td><code>HIT</code>、<code>MISS</code>、<code>EXPIRED</code>、<code>REVALIDATED</code>、<code>BYPASS</code>，见上文。被清理的副本在下一次请求时为 <code>EXPIRED</code> 或 <code>REVALIDATED</code>，并带 <code>X-Timestamp</code> 头</td></tr><tr><td><code>Age</code></td><td>副本已缓存的秒数</td></tr><tr><td><code>X-Cache-Key</code></td><td>缓存 Key 的摘要，两次请求的值不同即不是同一副本</td></tr></tbody></table>

没有规则命中的响应不带这些头。洞察页按 `X-Cache` 的值统计请求数与流量，见[洞察与日志](/zh/docs/edge/policies/cache/insight.md)。

## 不缓存的响应 <a href="#not-cached" id="not-cached"></a>

* 带 `Set-Cookie` 的响应，任何模式下都不缓存；命中缓存的响应也会去掉 `Set-Cookie`。
* 缓存时长算出为 0 的响应，见[缓存时长](/zh/docs/edge/policies/cache/configuration.md#ttl)。
* 响应 `Vary: *` 的内容永远不会命中；其它 `Vary` 头按头值分别缓存。

请求方法是 Key 的一部分，GET 与 HEAD 分开缓存，用 HEAD 预检不会为之后的 GET 填充缓存。请求体不参与 Key，非 GET/HEAD 的接口要用「绕过缓存」规则排除，见[配置场景](/zh/docs/edge/policies/cache/use-cases.md#bypass-dynamic)。`Authorization` 头不影响缓存。

`Accept-Encoding` 在生成 Key 前归一化为 gzip、zstd、br、deflate 之一或无，客户端写法不同的请求共用一份副本。

## 缓存安全 <a href="#security" id="security"></a>

共享缓存把一个请求的响应交给后续的其他请求，三类问题要在规则上避免：

* **缓存投毒**：源站按某个请求头返回不同内容（设备、语言、`Origin` 对应的 CORS 头）时，这个头必须加入缓存 Key，或由源站返回 `Vary`；否则第一个请求的响应会被缓存给所有人。不要把未进入 Key 的请求头原样写入响应体。
* **缓存欺骗**：默认规则按后缀缓存，源站若对 `/account/x.jpg` 这类不存在的路径回退到 `/account` 的内容，个性化页面就会被当作图片缓存，攻击者随后访问同一地址即可取得。防护：源站对动态路径返回 `Cache-Control: private`（源站优先模式下即不缓存），或把可缓存规则限定在 `/static/`、`/assets/` 这类真正的静态前缀。
* **私有内容进入公共副本**：带 `Set-Cookie` 的响应不会缓存，但登录后的页面通常不再下发 `Set-Cookie`；含个人信息的路径要用绕过规则排除，见[配置场景](/zh/docs/edge/policies/cache/use-cases.md#bypass-dynamic)。

## 存储 <a href="#storage" id="storage"></a>

缓存存放在每个边缘节点的本地磁盘，节点之间不共享：同一内容在每个节点各自回源一次，清理和预热也按节点生效。缓存时长决定多久不用回源确认，不决定副本在磁盘上保留多久：过期的副本仍留在磁盘上供回源校验使用。容量按磁盘自动分配，超限按最久未访问淘汰；30 天未被访问的副本即使尚未过期也会删除，低流量内容在节点上留不住，表现为反复 `MISS`。缓存目录、容量上限、保留期和索引区大小可以按节点覆盖，见[运行参数调整指南](/zh/docs/edge/edge/custom-config.md)，小文件为主的大容量节点通常需要调大索引区。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://www.axisnow.io/zh/docs/edge/policies/cache/how-it-works.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
