加入我们,于10月8日至10日在纽约市,学习关于GraphQL联邦和API平台工程的最新技巧、趋势和新闻。加入我们参加2024年纽约市的GraphQL峰会
文档
免费开始

配置缓存后端

如何配置Apollo Server的缓存


多数的功能利用了缓存后端(这些功能包括 自动持久化查询, 响应缓存插件response cache plugin,和 RESTDataSource)。 Apollo Server默认使用内存缓存,但您可以配置它使用不同的后端,例如Redis或Memcached。

您可以通过将 cache 选项传递给 ApolloServer 构造函数来指定缓存后端。您指定的缓存后端必须实现从 KeyValueCache 包中的 @apollo/utils.keyvaluecache 接口。

有很多缓存后端实现可供选择,包括Apollo提供的一些实现。例如,Apollo在 @apollo/utils.keyvaluecache 包中维护了一个 InMemoryLRUCache 的实现。Apollo还提供了一个包装类,名为 keyv(实现了多个缓存后端),在 KeyvAdapter 包中。

配置内存缓存

⚠️ 如果您正在使用Apollo Server 3,请参阅 这篇文章的上一版本 了解如何使用有界缓存来保护您的缓存免受拒绝服务攻击。默认情况下,Apollo Server 4的默认缓存是一个 有界 的内存缓存后端。

您可以使用 cache 构造函数选项来配置服务器以使用不同的后端(例如Redis或Memcached)。

如果您想配置默认的内存缓存,Apollo提供了从 InMemoryLRUCache 类,该类来自 @apollo/utils.keyvaluecache 包。

“InMemoryLRUCache”类是对lru-cache包的封装,默认内存最大约为30MiB。您可以像配置lru-cache包中的实例一样配置InMemoryLRUCache的实例,有关详细信息,请参阅lru-cache文档。您可以通过传递给ApolloServer构造函数的cache选项来使用Apollo的InMemoryLRUCache类,如下所示:

import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
const server = new ApolloServer({
cache: new InMemoryLRUCache(),
});

Apollo Server 4提供了上述代码段的功能,无需安装@apollo/utils.keyvaluecache包。

在此示例中,我们增加了默认大小并提供了默认的TTL。有关这些配置选项的更多信息,请参阅lru-cache文档

import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
const server = new ApolloServer({
// ...
cache: new InMemoryLRUCache({
// ~100MiB
maxSize: Math.pow(2, 20) * 100,
// 5 minutes (in seconds)
ttl: 300,
}),
});

配置外部缓存

Apollo不再直接维护任何缓存后端。相反,我们建议使用keyv包,以及通过KeyvAdapter类(由@apollo/utils.keyvadapter包提供)。

KeyvAdapter 包裹了一个 Keyv 实例,实现了 Apollo Server 需要的 KeyValueCache 接口。您可以使用 KeyvAdapter 类来包装一个 Keyv 实例,并像这样将其提供给 ApolloServer 构造函数的 cache 选项:

  1. 安装所需的包
npm install keyv @apollo/utils.keyvadapter
  1. 配置 Apollo Server 的 Apollo Server cache
import Keyv from 'keyv';
import { KeyvAdapter } from '@apollo/utils.keyvadapter';
const server = new ApolloServer({
// ...,
cache: new KeyvAdapter(new Keyv()),
});

实现自己的缓存后端

如果您的需求是专业的或者您想实现自己的缓存后端,您可以实现 KeyValueCache 接口并将其直接传递给 ApolloServer 构造函数。

下面的 KeyValueCache 接口:

interface KeyValueCache<V> {
get(key: string): Promise<V | undefined>;
// ttl is specified in seconds
set(key: string, value: V, options?: { ttl?: number | null }): Promise<void>;
delete(key: string): Promise<boolean | void>;
}

配置 Redis

The @keyv/redis 包使用底层的 ioredis 包。第二个选项参数通过传递给 ioredis.Redis 构造函数。请参阅 ioredis 文档以获取可用选项的列表。

首先安装所需的包

npm install keyv @keyv/redis @apollo/utils.keyvadapter

单个实例

import Keyv from "keyv";
import { KeyvAdapter } from "@apollo/utils.keyvadapter";
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new KeyvAdapter(new Keyv("redis://user:pass@localhost:6379")),
});

Redis Sentinel

import Keyv from "keyv";
import { KeyvAdapter } from "@apollo/utils.keyvadapter";
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new KeyvAdapter(
new Keyv("redis://user:pass@localhost:6379", {
sentinels: [
{ host: "localhost", port: 26379 },
{ host: "localhost", port: 26380 },
],
})
),
});

Redis 集群

“@keyv/redis”@keyv/redis 包不支持直接使用 ioredis.Cluster。相反,我们可以创建自己的 ioredis.Cluster 实例并将其作为对象传递给 keyv 作为存储对象。查看 ioredis.Cluster 文档 以获取可用选项列表。

首先安装我们需要的包

npm install keyv @keyv/redis ioredis @apollo/utils.keyvadapter
import Keyv from "keyv";
import KeyvRedis from "@keyv/redis";
import Redis from "ioredis";
import { KeyvAdapter } from "@apollo/utils.keyvadapter";
const cluster = new Redis.Cluster([
{ host: "localhost", port: 26379 },
{ host: "localhost", port: 26380 },
]);
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new KeyvAdapter(new Keyv({ store: new KeyvRedis(cluster) }), {
disableBatchReads: true,
}),
});

注意 disableBatchReads 选项。这个选项禁用了批处理,而 ioredis.Cluster 不支持批处理。

配置Memcache

“@keyv/memcache”@keyv/memcache 包在底层使用了 memjs 包。其二选项 argument 传递给 memjs.Client.create()。查看 memjs 文档 以获取可用选项列表。

首先安装所需的包

npm install keyv @keyv/memcache @apollo/utils.keyvadapter
import Keyv from "keyv";
import KeyvMemcache from "@keyv/memcache";
import { KeyvAdapter } from "@apollo/utils.keyvadapter";
// servers is a comma-separated list of strings
const servers = [
"user:pass@localhost:11211",
"user:pass@localhost:11222"
].join(",");
const memcache = new KeyvMemcache(servers, {
retries: 10,
expires: 60,
});
const server = new ApolloServer({
typeDefs,
resolvers,
cache: new KeyvAdapter(new Keyv({ store: memcache })),
});

处理缓存获取错误

为了提供通过客户端(例如,Redis)连接的缓存后端容错,我们建议使用来自 @apollo/utils.keyvaluecacheErrorsAreMissesCache 包装器。如果缓存不可用并且您的请求引发错误,ErrorsAreMissesCache 将该错误视为缓存未命中。同时,您的缓存客户端可以持续尝试重新连接到您的缓存后端,直到一切恢复正常,如下所示:

import Keyv from "keyv";
import { KeyvAdapter } from "@apollo/utils.keyvadapter";
import { ErrorsAreMissesCache } from "@apollo/utils.keyvaluecache";
const redisCache = new Keyv("redis://user:pass@localhost:6379");
const faultTolerantCache = new ErrorsAreMissesCache(
new KeyvAdapter(redisCache),
);

遗留缓存实现

Apollo Server 3.9 之前的版本使用 apollo-server-caching 包来实现缓存。由于 apollo-server-caching 包不再维护,我们不推荐使用它。

“KeyValueCache” 接口已移位,现位于 @apollo/utils.keyvaluecache 包中。

“InMemoryLRUCache” 类也已移至 @apollo/utils.keyvaluecache 包。现在的 InMemoryLRUCache 类使用版本 7 的 lru-cache,接受不同的配置选项,不再允许缓存无限制。

上一页
缓存
下一页
自动持久化查询
打分文章评分.css-1r5v3i6{display:-ms-grid;display:grid;grid-gap:var(--chakra-space-6);-ms-grid-columns:repeat(auto-fit, minmax(100px, 1fr));grid-template-columns:repeat(auto-fit, minmax(100px, 1fr));border-top-width:1px;padding:var(--chakra-space-12);}@media screen and (min-width: 48em){.css-1r5v3i6{grid-gap:var(--chakra-space-8);}}

公司