内存缓存
配置路由缓存以查询计划和自动持久化查询
两者都GraphOS 路由器和Apollo 路由器核心使用内存中的LRU缓存存储以下数据:
- 生成的查询计划
- 自动持久化查询(APQ)
- introspection响应
您可以配置生成的查询计划和APQ(但不是introspection响应)的某些缓存行为。
💡 提示
如果您有GraphOS 企业版,您还可以配置一个Redis支持的分布式缓存,允许多个路由器实例共享缓存的值。有关详细信息,请参阅GraphOS 路由器中的分布式缓存。
性能提升与稳定性
该路由器是一个高度可扩展且低延迟的运行时。即使在不开启所有缓存的情况下,处理操作和查询计划的时间(纳秒到毫秒)与整个supergraph请求相比,仍然非常小(在极端情况下,操作和supergraph非常大时除外)。缓存为运行大型图提供了稳定性,确保您在每个操作上的开销保持一致,而不是大幅度提高。如果您想验证操作缓存的性能优势,请查看路由器中的跟踪和指标来获取操作前后度量结果。但在极端的大规模边缘情况下,我们发现缓存可以将创建查询计划所需的时间节省2-10倍,这在整体请求中仍是一个很小的部分。
缓存查询计划
每当您的路由器收到GraphQL 操作时,它就会生成一个查询计划来确定需要查询哪些子图以解析该操作。
通过缓存以前生成的查询计划,当客户端稍后发送相同的操作时,您的路由器可以跳过重新生成它们。这提高了路由器的响应速度。
GraphOS 路由器默认启用查询计划缓存。在您路由器的YAML 配置文件中,您可以配置缓存中查询计划条目的最大数量,如下所示:
supergraph:query_planning:cache:in_memory:limit: 512 # This is the default value.
在架构重新加载时,缓存将被重置,查询需要再次进行查询计划...
supergraph:query_planning:# Pre-plan the 100 most used operations when the supergraph changes. (Default is "0", disabled.)warmed_up_queries: 100cache:in_memory:limit: 512
缓存预热
在加载新架构时,某些查询的查询计划可能会改变,因此无法重用缓存中的查询计划。
为了防止查询计划缓存失效后的延迟增加,路由器预计算以下查询计划:
- 缓存中最常用的查询。
- 持久化查询的完整列表。
在路由器切换流量到新架构之前,将预先计算的计划缓存。
默认情况下,路由器使用缓存中已存在的30%的查询进行缓存预热,但可以按以下方式配置:
supergraph:query_planning:# Pre-plan the 100 most used operations when the supergraph changeswarmed_up_queries: 100
要获取有关规划和预热的更多信息,请使用以下指标(其中<存储>
可以是用于分布式缓存的redis
或内存中的内存
):
计数器
apollo_router_cache_size{kind="query planner", storage="<storage>}"
:缓存当前大小(仅适用于内存缓存)apollo_router_cache_hit_count{kind="query planner", storage="<storage>}"
apollo_router_cache_miss_count{kind="query planner", storage="<storage>}"
直方图
apollo.router.query_planning.plan.duration
:查询计划所需时间apollo_router_schema_loading_time
:加载架构所需时间apollo_router_cache_hit_time{kind="query planner", storage="<storage>}"
:从缓存获取值所需时间apollo_router_cache_miss_time
通常,我们会查看apollo_router_cache_size
和缓存命中率来定义内存缓存的正确大小,然后查看apollo_router_schema_loading_time
和apollo.router.query_planning.plan.duration
来决定我们希望花费多少时间预热查询。
使用分布式缓存的缓存预热
如果路由器正在使用分布式缓存进行查询计划的存储,预热阶段也会将新的查询计划存储到Redis中。由于所有路由器实例的内存缓存中可能具有相同的查询分布,因此在预热之前会对查询列表进行随机排序,以便每个路由器实例可以以不同的顺序执行查询并通过缓存共享其结果。
模式感知查询哈希
查询计划缓存键使用了一种专门针对GraphQL查询设计的哈希算法,使用模式。如果一个模式更新不会影响查询(例如:添加了一个字段),那么查询哈希将保持不变。查询计划缓存可以在预热期间使用该键来检查是否可以重用缓存条目而不是再次进行计划。
可以通过此选项激活
supergraph:query_planning:warmed_up_queries: 100experimental_reuse_query_plans: true
缓存自动持久化查询(APQ)
自动持久化查询(APQ)允许GraphQL客户端向服务器发送其查询字符串的哈希值,而不是发送查询字符串本身。当查询字符串非常大时,这可以显著减少网络使用量。
路由器支持在使用和子图之间的通信中使用APQ:
- 在与客户端的通信中,路由器充当GraphQL服务器,因为它从客户端接收查询。
- 在与子图的通信中,路由器充当GraphQL客户端,因为它向子图发送查询。
由于路由器在这两种交互中的角色不同,您需要分别配置这些APQ设置。
与客户端的APQ
路由器默认启用对客户端操作的APQ缓存。在您的路由器的YAML配置文件中,您可以配置缓存中APQ条目的最大数量,如下所示:
apq:router:cache:in_memory:limit: 512 # This is the default value.
您还可以完全禁用客户端APQ支持,如下所示:
apq:enabled: false
与子图的APQ
默认情况下,路由器发送查询到其子图时不使用APQ。
在您的路由器的YAML配置文件中,您可以通过全球设置和子图设置来配置此APQ支持:
apq:subgraph:# Disables subgraph APQ globally except where overridden per-subgraphall:enabled: false# Override global APQ setting for individual subgraphssubgraphs:products:enabled: true
在上面的示例中,子图APQ除了products子图外都已被禁用。