Apollo服务器-关于缓存/数据源选项的困惑

atk*_*yla 4 apollo apollo-server apollostack apollo-client

docs(https://www.apollographql.com/docs/apollo-server/features/data-sources.html#Using-Memcached-Redis-as-a-cache-storage-backend)显示如下代码:

const { RedisCache } = require('apollo-server-cache-redis');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: new RedisCache({
    host: 'redis-server',
    // Options are passed through to the Redis client
  }),
  dataSources: () => ({
    moviesAPI: new MoviesAPI(),
  }),
});
Run Code Online (Sandbox Code Playgroud)

我想知道如何使用该cache密钥,因为考虑到缓存实际上是自定义实现的MoviesAPI(),然后通过来使用context.dataSources.moviesAPI.someFunc()。例如,假设我想为SQL数据库实现自己的缓存。看起来像

  cache: new RedisCache({
    host: 'redis-server',
  }),
  dataSources: () => ({
    SQL: new SQLCache(),
  }),
});
Run Code Online (Sandbox Code Playgroud)

在哪里SQLCache有我自己的功能连接到RedisCache类似:

  getCached(id, query, ttl) {
    const cacheKey = `sqlcache:${id}`;

    return redisCache.get(cacheKey).then(entry => {
      if (entry) {
        console.log('CACHE HIT!');
        return Promise.resolve(JSON.parse(entry));
      }
      console.log('CACHE MISS!');
      return query.then(rows => {
        if (rows) redisCache.set(cacheKey, JSON.stringify(rows), ttl);
        return Promise.resolve(rows);
      });
    });
  }
Run Code Online (Sandbox Code Playgroud)

因此,这意味着我必须RedisCache在这两个ApolloServer cache关键和dataSource实施。显然,RedisCachedataSource实现中使用了,但是该ApolloServer cache键到底有什么作用?

同样在客户端上,示例大部分显示使用InMemoryCache代替Redis缓存。客户端Apollo缓存应该是与服务器缓存不同的缓存,还是应该RedisCache在两个地方都使用相同的缓存?

Dan*_*den 5

据我所知,cache传递给的ApolloServer严格用于a的上下文中RESTDataSource。从REST端点获取资源时,服务器将检查Cache-Control响应上的标头,如果存在标头,则将适当地缓存资源。这意味着,如果标头为max-age=86400,则响应将以24小时的TTL进行缓存,并且在缓存条目到期之前,将使用它而不是调用相同的REST URL。

这与您已实现的缓存机制不同,因为代码会缓存来自数据库的响应。它们的意图是相同的,但是它们使用不同的资源。您的代码有效复制ApolloServer所做的唯一方法cache是,如果您DataSource为REST端点编写了类似的代码。

虽然这两个缓存都减少了处理GraphQL响应所花费的时间(从缓存中获取的速度明显快于从数据库中获取的速度),但客户端缓存减少了必须向服务器发出的请求的数量。最值得一提的是,InMemoryCache您可以在站点的不同位置(例如React中的不同组件)重用一个查询,而只获取一次查询。

因为客户端缓存是规范化的,所以这也意味着如果通过一个查询获取资源时是否已经缓存了资源,则有可能避免在另一查询请求时重新获取资源。例如,如果您通过一个查询获取用户列表,然后通过另一个查询获取用户,则可以将客户端配置为在缓存中查找该用户,而不用进行第二次查询。

重要的是要注意,尽管缓存在服务器端的资源通常具有TTL,InMemoryCache但没有。而是使用“提取策略”来确定单个查询的行为。例如,这使您拥有始终从服务器获取的查询,而不管缓存中的内容如何。

希望这有助于说明服务器端缓存和客户端缓存都是有用的,但方式却大不相同。