GraphOS 路由器中的子图实体缓存
配置 Redis 支持的实体缓存
此功能仅适用于 GraphOS 企业计划.
您可以通过免费注册来测试它 企业试用.
此功能处于 预览。您的疑问和反馈非常受欢迎—不妨联系您的 Apollo 联系人.
了解GraphOS 路由器 可以使用 Redis 缓存 子图 查询 响应,以提高 supergraph 中实体的查询延迟。
概览
一个 实体 从一个或多个 子图 获取其 字段。为了响应用户对实体的请求,GraphOS Router 必须进行多次子图请求。不同用户请求同一实体可能生成重复的、相同的子图请求。
实体缓存允许路由器以缓存的子图响应来响应相同的子图查询。路由器使用Redis缓存子图查询响应中的数据。由于缓存的键是按子图和实体设置的,因此在不同客户端中,即使查询参数相同或不同,相同的客户端查询也会访问相同的子图响应数据缓存条目。
实体缓存的优点
与缓存整个客户端响应相比,实体缓存可以更精细地控制:
- 缓存数据的有效期(TTL)
- 要缓存的数据量
当缓存整个客户端响应时,由于应用程序数据经常变化,路由器必须将存储的TTL设置得更短。实时数据需要更频繁的更新。
客户端响应缓存可能无法在用户之间共享,因为应用程序数据可能包含个人和私人信息。客户端响应缓存还可能在客户端响应之间复制大量数据。
例如,考虑Products
和Inventory
子图来自实体指南:
type Product @key(fields: "id") {id: ID!name: String!price: Int}
type Product @key(fields: "id") {id: ID!inStock: Boolean!}
假设电子商务应用程序的客户端对购物车中的每个产品请求以下内容:
- 从
Products
子图中的产品名称和价格。 - 从
Inventory
子图中的产品库存可用性。
如果缓存整个客户端响应,由于购物车数据经常变化,并且实时库存需要保持最新,因此需要较短的TTL。由于每个购物车都是个人的,因此客户端响应缓存可能无法在用户之间共享。客户端响应缓存也可能由于相同的产品可能出现在多个购物车中而复制大量数据。
在这个示例中启用了实体缓存后,路由器可以:
- 分别以长TTL存储每个产品的描述和价格。
- 最小化每个客户端请求触发的子图请求次数,一些客户端请求可以加载数据缓存,无需进行子图请求。
- 共享产品缓存,供所有用户使用。
- 按用户缓存购物车,数据量较小。
- 使用短生存时间(TTL)缓存库存数据或不使用缓存。
使用实体缓存
按照以下指南启用和配置GraphOS Router中的实体缓存:
先决条件
要在GraphOS Router中使用实体缓存,您必须设置以下内容:
- 您的路由器实例可以与其通信的Redis实例或集群
- 一个GraphOS企业计划,使您的路由器连接到GraphOS。
配置路由器以进行实体缓存
在router.yaml
中配置preview_entity_cache
:
- 全局启用实体缓存。
- 使用与分布式缓存中描述的相同约定配置Redis。
- 按子图配置实体缓存,每个子图可对禁用实体缓存和TTL进行覆盖。
例如:
# Enable entity caching globallypreview_entity_cache:enabled: true# Configure Redisredis:urls: ["redis://..."]timeout: 5ms # Optional, by default: 2msttl: 24h # Optional, by default no expirationsubgraph:all:enabled: true# Configure entity caching per subgraph, overrides options from the "all" sectionsubgraphs:products:ttl: 120s # overrides the global TTLinventory:enabled: false # disable for a specific subgraph
配置生存时间(TTL)
除了为Redis中所有条目的全局TTL进行配置外,GraphOS Router还遵守Cache-Control
头返回的子图响应。它通过聚合所有响应部分的TTL信息来生成客户端响应的Cache-Control
头。使用实体缓存的所有子图都必须配置TTL,无论是定义在特定子图配置中还是从全局配置继承。
自定义Redis缓存键
如果您需要将特定请求的数据存储在不同的缓存条目中,您可以通过apollo_entity_cache::key
上下文条目配置缓存键。
本条目包含一个包含 all
字段 的对象,可影响一个客户端请求下的所有 子图 请求,以及以子图 操作名称 命名的字段,以影响单个子图查询。字段的值可以是任何有效的 JSON 值(对象、字符串等)。
{"all": 1,"subgraph_operation1": "key1","subgraph_operation2": {"data": "key2"}}
实现说明
Cache-Control报头要求
目前 路由器 无法了解哪些类型或 字段 应该被缓存,因此它要求 子图 在其响应中设置 Cache-Control
报头以指示其应该被存储。
错误响应不缓存
为了防止瞬态错误影响缓存长时间, 子图 响应中的错误不进行缓存。
授权和实体缓存
当与路由器的 路由器 的 授权指令 一起使用时,缓存条目根据授权上下文进行分隔。如果查询包含需要特定作用域的 字段,则提供该作用域的请求具有与不提供该作用域的请求不同的缓存条目。这意味着需要授权的数据仍然可以安全地进行缓存,甚至在用户之间共享,无需在用户的角色更改时进行无效化,因为它们的请求会自动导向缓存的不同部分。
模式更新和实体缓存
在模式更新时, 路由器 确保未受影响的查询保持其缓存条目。受影响的 字段 的查询需要再次进行缓存,以确保路由器不会从更新之前提供无效数据。
不支持实体缓存失效
缓存失效功能尚未支持,计划在未来的版本中推出。