3. OpenAPI 与缓存的关系:API 网关缓存、服务端缓存、客户端缓存、HTTP 缓存头

在 OpenAPI 场景中,缓存不是单一组件,而是一个贯穿请求全路径的分层体系。每一层缓存解决不同的问题,也引入不同的一致性风险。理解各层缓存的位置、机制与适用场景,是设计缓存一致性策略的前提。

3.1 缓存分层全景

从客户端发起请求到后端服务返回响应,缓存可能出现在四个关键位置:

  1. 客户端缓存 — 浏览器、移动 App、网关 SDK 本地存储。
  2. API 网关缓存 — 网关节点(如 Kong、APISIX、Nginx)的共享或本地缓存。
  3. 服务端缓存 — 应用层本地缓存(Caffeine、Guava)或分布式缓存(Redis、Memcached)。
  4. HTTP 缓存头 — 贯穿上述各层的控制协议(Cache-Control、ETag、Last-Modified)。
核心原则:越靠近客户端的缓存,延迟收益越大,但一致性控制越难;越靠近服务端的缓存,一致性越强,但延迟收益递减。
OpenAPI 缓存分层架构 OpenAPI 缓存分层架构 客户端缓存 浏览器 / App / SDK API 网关缓存 Kong / APISIX / Nginx 服务端缓存 Redis / Caffeine HTTP 缓存头:Cache-Control · ETag · Last-Modified 各层缓存的关键特征 • 客户端缓存:零网络延迟,但无法被服务端主动失效;依赖 HTTP 头控制有效期。 • 网关缓存:可被网关统一管理,支持 TTL 和主动失效;适合聚合响应和静态数据。 • 服务端缓存:一致性最强,支持分布式失效和事务级更新;延迟收益相对最小。 • HTTP 缓存头:跨层控制协议,决定“谁能缓存”“缓存多久”“如何验证新鲜度”。

3.2 API 网关缓存

API 网关处于南北流量的枢纽位置,是实施缓存的高性价比节点。网关缓存通常用于:

  • 聚合响应缓存:将多个后端服务的响应合并后整体缓存,减少客户端等待时间。
  • 静态数据缓存:配置信息、公共字典、版本号等变化频率极低的数据。
  • 限流/熔断状态缓存:网关自身的状态数据,不依赖后端。
网关产品 缓存机制 失效方式 一致性等级
Kong Plugin (proxy-cache) TTL + 手动清除 最终一致性
APISIX Plugin (proxy-cache) TTL + Admin API 清除 最终一致性
Nginx + Lua lua-resty-lrucache / shared dict TTL + Lua 脚本主动失效 最终一致性 / 可配置
Spring Cloud Gateway 本地缓存 + Redis TTL + 消息广播失效 可达到强一致性
避坑提示:网关缓存默认是最终一致性。如果业务要求“写入后立即读取到最新数据”,必须在网关层禁用缓存,或使用 Cache-Control: no-cache 头绕过。

3.3 服务端缓存

服务端缓存分为本地缓存和分布式缓存两类,它们在 OpenAPI 场景中的角色差异明显:

维度 本地缓存(Caffeine / Guava) 分布式缓存(Redis / Memcached)
数据容量 受 JVM 堆内存限制 可水平扩展,容量大
访问延迟 纳秒级(堆内访问) 微秒级(网络 RTT)
一致性 单机强一致,多机需广播 依赖缓存策略,可配置强一致
典型场景 热点数据、配置、用户会话 共享数据、排行榜、分布式锁
失效复杂度 低(TTL + 手动清除) 中(TTL + 发布订阅 + 主动删除)
架构建议:在 OpenAPI 场景中,推荐采用本地缓存 + 分布式缓存两级架构。本地缓存扛热点,分布式缓存做共享和兜底。两级之间通过 TTL 和失效消息保持最终一致性。

3.4 客户端缓存

客户端缓存是距离用户最近的缓存层,通常由浏览器或移动 App 的 HTTP 缓存模块自动管理。在 OpenAPI 设计中,客户端缓存主要依赖 HTTP 响应头 来控制:

  • Cache-Control: max-age=3600 — 告诉客户端该响应在 3600 秒内可直接使用,无需请求服务端。
  • Cache-Control: no-cache — 客户端必须向服务端验证缓存是否有效(配合 ETag 使用)。
  • Cache-Control: no-store — 禁止客户端缓存该响应(敏感数据场景)。
  • Expires — 绝对过期时间(已被 Cache-Control 取代,但部分旧客户端仍使用)。
关键认知:客户端缓存一旦生效,服务端无法主动失效。因此,对于需要强一致性的 API(如库存、余额),必须设置 Cache-Control: no-cache 或 max-age=0,让客户端每次请求都到服务端验证。

3.5 HTTP 缓存头详解

HTTP 缓存头是连接所有缓存层的控制协议。在 OpenAPI 设计中,最核心的三个头是 Cache-Control、ETag 和 Last-Modified。

3.5.1 Cache-Control 指令

指令 含义 典型值 适用场景
public 允许所有缓存节点(网关、CDN、客户端)缓存 public, max-age=60 公开数据、静态资源
private 仅允许客户端缓存,禁止网关/CDN 缓存 private, max-age=300 用户个性化数据
no-cache 允许缓存,但每次使用前必须向服务端验证 no-cache 需要强验证的 API
no-store 禁止任何缓存 no-store 敏感数据、支付接口
max-age 缓存有效期的秒数 max-age=3600 通用有效期控制
s-maxage 仅对共享缓存(网关/CDN)生效,覆盖 max-age s-maxage=600 网关与客户端差异化控制
must-revalidate 过期后必须向源服务器验证,不可使用过期缓存 must-revalidate 强一致性要求

3.5.2 ETag 与条件请求

ETag 是服务端为响应内容生成的唯一标识(通常是哈希值或版本号)。客户端在后续请求中通过 If-None-Match 头携带该值,服务端比较后决定返回 304 Not Modified(缓存有效)或 200 OK(新内容)。

// 服务端响应
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "abc123xyz"
Cache-Control: no-cache

// 客户端后续请求
GET /api/v1/products/42
If-None-Match: "abc123xyz"

// 服务端响应(内容未变)
HTTP/1.1 304 Not Modified
ETag: "abc123xyz"
// 无响应体,客户端继续使用本地缓存
最佳实践:在 OpenAPI 中,对列表查询和详情查询接口优先使用 ETag + Cache-Control: no-cache 组合。这既避免了无效的响应体传输,又保证了每次请求都经过服务端验证,是性能与一致性兼顾的经典方案。

3.6 缓存头组合策略

根据 API 的一致性要求,推荐以下缓存头组合模板:

一致性等级 Cache-Control ETag 典型 API 示例
强一致 no-store 不使用 订单创建、支付提交
会话一致 no-cache 必须使用 用户信息、购物车
最终一致(短 TTL) public, max-age=60 可选 商品库存(允许秒级延迟)
最终一致(长 TTL) public, max-age=3600, s-maxage=600 可选 静态配置、字典数据
HTTP 缓存头决策流程 HTTP 缓存头决策流程 API 响应需要缓存吗? Cache-Control: no-store 需要强验证吗? Cache-Control: no-cache 设置 max-age / s-maxage 是否使用 ETag? 生成 ETag 并返回 仅依赖 TTL 过期 最终响应:Cache-Control + 可选 ETag / Last-Modified

3.7 本章小结

  • OpenAPI 缓存体系分为客户端、网关、服务端三层,外加 HTTP 缓存头作为跨层控制协议。
  • API 网关缓存适合聚合响应和静态数据,默认最终一致性,需关注失效延迟。
  • 服务端缓存推荐“本地 + 分布式”两级架构,本地扛热点,分布式做共享。
  • 客户端缓存无法被服务端主动失效,强一致场景必须使用 no-cache 或 no-store。
  • ETag + Cache-Control: no-cache 是兼顾性能与一致性的黄金组合,适用于大多数查询类 API。
  • 缓存头策略应根据 API 的一致性等级选择,避免一刀切使用 max-age 或 no-store。