← 返回文章列表

HTTP 状态码与缓存头:实用速查与一套可套用的策略

HTTP缓存

状态码:先看类别,再看具体值

类别含义常见值
1xx信息100 Continue、101 协议切换
2xx成功200、201 已创建、204 无内容
3xx重定向301 永久、302 临时、304 未修改、307/308 保持方法
4xx客户端错误400、401 未认证、403 无权限、404、409 冲突、429 限流
5xx服务端错误500、502 网关错误、503 不可用、504 网关超时

四个容易混淆的点

  • 401 vs 403:401 是「你是谁」,403 是「知道你是谁,但不给你」;
  • 301 vs 308:同为永久重定向,308 保证请求方法与请求体不变;302 与 307 的关系同理;
  • 200 但业务失败:不少接口用 200 + 业务错误码表示失败,客户端必须读响应体;
  • 502 vs 504:都是网关问题,502 是上游返回了无效响应,504 是上游超时。

缓存头速查

响应头作用常用值
Cache-Control缓存策略主体no-store / no-cache / max-age=3600 / immutable
ETag资源指纹,用于协商缓存"abc123"(配合 If-None-Match)
Last-Modified最后修改时间配合 If-Modified-Since
Vary按哪些请求头区分缓存Accept-Encoding、Accept-Language

一套可直接套用的策略

  1. 文件名带哈希的构建产物:Cache-Control: public, max-age=31536000, immutable(文件名一变即更新);
  2. HTML 页面:max-age=0, must-revalidate(保证发布后即时生效);
  3. API 响应:私有数据用 no-store,可共享的公开数据用较短 max-age 配合 ETag;
  4. 静态图片与字体:长 max-age,并配合 Vary: Accept-Encoding。

常见坑

  • 只设 max-age 不设 immutable:用户刷新时仍会发起验证请求;
  • 给 HTML 设长缓存:发版后用户看到旧页面,且中间缓存可能长期不回源;
  • ETag 与 CDN 配置不一致:导致协商缓存失效或缓存错乱;
  • 忽略 Vary:可能把 gzip 内容发给不支持压缩的客户端。

排查建议

用浏览器开发者工具的 Network 面板看「大小」列:显示 from disk cache 或 memory cache 说明命中强缓存;显示 304 说明命中协商缓存。再核对响应头里的 Cache-Control 是否与预期一致,通常一步就能定位问题。服务端排查时,逐层检查:源站响应头 → CDN 缓存规则 → 浏览器缓存状态。

常见问题

no-cache 是不缓存吗?不是。no-cache 表示「可以缓存,但每次使用前必须向服务器验证」,真正完全不缓存是 no-store。304 为什么没有响应体?它是「未修改」的标记,浏览器直接使用本地副本,因此不带正文。接口要不要缓存?看数据是否共享:用户私有数据不应被中间缓存共享,公开且变更不频繁的数据可以。

状态码与缓存头的配合

状态码不仅是给调用方看的,它也参与缓存决策,两者必须一起设计。

  1. 可缓存性取决于方法与状态码:默认情况下,成功响应可被缓存,而错误响应通常不被缓存。若希望错误也被短暂缓存以减轻下游压力,需要显式声明,并严格控制时长。
  2. 重定向与永久性:永久重定向应谨慎使用,一旦浏览器缓存就很难撤除;临时重定向适合灰度与维护场景。
  3. 验证器要用对:内容有变更时给出新的验证器,未变更时返回表示“未修改”的结果,让客户端复用本地副本,能显著降低带宽。
  4. 区分“未找到”与“已删除”:前者表示当前不存在,后者表示曾经存在并已移除。搜索引擎与客户端对二者的处理不同,混用会造成索引异常。
  5. 冲突与前置条件:并发更新应使用前置条件相关的状态码与验证器配合,让调用方能区分“请求有误”与“数据被他人修改”。

常见误区

把所有错误都返回同一个状态码会让客户端无法区分处理策略,例如需要重试的暂时性错误与需要修改请求的参数错误被混在一起。为不同语义分配稳定且明确的状态码,是接口可用性的基础工作。

与监控的配合

状态码分布本身就是重要的监控指标:客户端错误比例突然上升通常意味着调用方变更或文档有误,服务端错误上升则指向自身缺陷。把不同类别的状态码分开统计并设阈值告警,比只看总错误率更能快速定位问题来源。