HTTP 缓存排障:分清 no-cache、no-store 和 ETag

举报
yd_239005675 发表于 2026/10/13 00:15:18 2026/10/13
【摘要】 本文从 HTTP 缓存排障出发,分清 no-cache、no-store、max-age、304 与 ETag 的语义,并给出浏览器、网关和源站的分层检查步骤。

浏览器明明拿到了 304,为什么页面还是发起了请求?接口响应里写了 no-cache,是否代表完全不能缓存?遇到“缓存不生效”时,如果只盯着状态码,很容易把缓存新鲜度、重新验证和禁止存储混在一起。本文从排障角度梳理常见指令,并给出一套可复现的检查顺序。

1. 先把“缓存”拆成三个问题

一次响应是否被缓存,至少要分开看三个问题:缓存能不能存、存了以后多久算新鲜、变旧后是否需要向源站验证。Cache-Control 的不同指令分别回答这些问题。

max-age=60 表示响应在 60 秒内可以按新鲜响应复用。它描述的是新鲜度,并不等于浏览器 60 秒内绝对不会发请求;用户强制刷新、缓存策略和请求头都可能改变行为。

no-store 的含义更严格:缓存不得存储请求或响应的任何部分,也不能用这份响应满足后续请求。它适合包含一次性凭证或敏感结果的响应,但它不会替代传输加密、权限控制和日志脱敏。

no-cache 容易被误解。它不是“不允许存储”,而是每次复用前都必须转发请求进行验证,并在验证成功后才能继续使用已保存的响应。也就是说,响应可以留在缓存里,但不能未经验证直接拿来用。

2. 304 不是“没有缓存”

客户端带着 If-None-Match 或 If-Modified-Since 发起条件请求。源站判断资源没有变化时,可以返回 304 Not Modified,不重复传输正文。客户端随后使用本地保存的表示,因此网络面板里会看到一次请求,但响应体大小很小。

304 只适用于条件 GET 或 HEAD。它不能单独证明缓存一定命中,也不能证明业务数据已经更新;要确认复用的内容,应查看响应头里的 ETag、Last-Modified、Age、Cache-Control 和 Via 等字段,并确认浏览器的 Size 列是否标记为缓存读取。

如果服务端每次生成不同的 ETag,即使正文没有变化,条件请求也会得到 200;如果中间层删除了 ETag,客户端就无法按实体标签验证。排查时应分别抓取浏览器到网关、网关到源站的请求,确认条件头是否在链路中保留。

3. ETag 是版本标识,不是加密摘要

ETag 是资源表示的实体标签,可以是强标签,也可以带 W/ 前缀表示弱比较。应用不应把它当作安全签名,也不应把用户权限信息编码进标签。它的目标是帮助缓存判断“这份表示是否仍然是同一个版本”。

常见流程如下:

第一次响应:ETag: "v42"
后续请求:If-None-Match: "v42"
未变化:返回 304
已变化:返回 200 和新的 ETag

多节点部署时,所有节点需要对同一资源生成稳定且一致的标签,否则请求在不同节点间切换时会出现“有时 304、有时 200”。如果资源依赖用户身份或地区,还要检查 Vary 以及共享缓存的隔离规则,避免把一个用户的表示错误地提供给另一个用户。

4. 一套不依赖猜测的排障顺序

第一步,确认请求 URL、查询参数和请求方法完全一致。缓存键通常包含这些信息,参数顺序或版本号变化都可能导致新请求。

第二步,记录完整的缓存相关响应头:Cache-Control、Expires、ETag、Last-Modified、Vary、Age,以及代理添加的 Via 或 X-Cache。不要只截取状态码。

第三步,检查请求头是否带了 Cache-Control: no-cache、Pragma: no-cache 或 Cookie。客户端主动要求重新验证时,服务端返回 304 仍然是正常现象。

第四步,绕过浏览器直接请求网关和源站,比较两段响应的 ETag、Date 和 Cache-Control。若源站正确而网关错误,重点检查反向代理的缓存规则;若源站标签不稳定,再回到应用生成逻辑。

第五步,构造一个内容明确变化的测试版本,并记录从发布到命中新版本的时间。不要用“我刚改了文件但页面没变”作为唯一证据,因为中间可能存在服务端渲染缓存、CDN 缓存和浏览器缓存三层。

5. 安全和一致性边界

登录态、支付结果、个人资料等响应应谨慎设置 private 或 no-store,并检查共享缓存是否真的遵守规则。Cache-Control: no-store 不是隐私保护的完整方案,敏感数据仍可能出现在浏览器历史、应用日志、监控采样或错误报告中。

对静态脚本和样式,可以使用带内容哈希的文件名配合较长 max-age;发布新版本时生成新文件名,避免依赖缓存失效的精确时间。对必须快速更新的配置接口,可以短 max-age、no-cache 验证或显式版本号换取更强的一致性。

缓存策略是性能和一致性的取舍。先分清存储、新鲜度和验证,再结合请求头、响应头和链路中的每一层代理定位问题,通常比反复点击强制刷新更快找到根因。

写作说明:本文由 AI 辅助编写,示例为独立构造的通用技术说明。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。