Apollo Server - путаница с параметрами кэша / источника данных - PullRequest
0 голосов
/ 18 ноября 2018

Документы (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(),
  }),
});

Мне было интересно, как используется ключ cache, учитывая, что кажется, что кеширование на самом деле реализовано в чем-то специальнокак MoviesAPI(), а затем используется через context.dataSources.moviesAPI.someFunc(). Например, скажем, я хотел реализовать свой собственный кэш для базы данных SQL. Это выглядело бы как

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

, где 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);
      });
    });
  }

Это означает, что у меня есть RedisCache как в ключе ApolloServer cache, так и в реализации dataSource. Понятно, что используется RedisCacheв реализации dataSource, но что именно делает этот ключ ApolloServer cache?

Также на клиенте примеры в основном показывают использование InMemoryCache вместо кэша Redis. Если клиент Apolloкеш - это кеш, отличный от кеша сервера, или один и тот же кеш, как RedisCache, должен быть в обоих местах?

1 Ответ

0 голосов
/ 18 ноября 2018

cache, переданный ApolloServer, насколько мне известно, строго используется в контексте RESTDataSource. При извлечении ресурсов из конечной точки REST сервер проверяет заголовок Cache-Control в ответе и, если он существует, соответствующим образом кэширует ресурс. Это означает, что если заголовок равен max-age=86400, ответ будет кэшироваться с TTL 24 часа, и до истечения срока действия записи в кэше он будет использоваться вместо вызова того же URL-адреса REST.

Это отличается от механизма кэширования, который вы реализовали, поскольку ваш код кэширует ответ из базы данных. Их намерения одинаковы, но они работают с разными ресурсами. Единственный способ, которым ваш код эффективно продублирует то, что уже делает cache ApolloServer, - это если бы вы написали аналогичный DataSource для конечной точки REST.

Хотя оба этих кэша сокращают время, необходимое для обработки вашего ответа GraphQL (выборка из кэша заметно быстрее, чем из базы данных), кэширование на стороне клиента уменьшает количество запросов, которые должны быть отправлены на ваш сервер. В частности, InMemoryCache позволяет вам повторно использовать один запрос в разных местах вашего сайта (например, в различных компонентах React), получая запрос только один раз.

Поскольку кэш на стороне клиента нормализован, это также означает, что если ресурс уже кэшируется при выборке с помощью одного запроса, вы можете избежать его повторного добавления при запросе с другим запросом. Например, если вы извлекаете список пользователей с одним запросом, а затем извлекаете пользователя с другим запросом, ваш клиент может быть настроен на поиск пользователя в кэше вместо выполнения второго запроса.

Важно отметить, что, хотя ресурсы, кэшированные на стороне сервера, обычно имеют TTL, InMemoryCache не имеет. Вместо этого он использует «политики выборки» для определения поведения отдельных запросов. Это позволяет вам, например, иметь запрос, который всегда выбирает с сервера, независимо от того, что находится в кэше.

Надеюсь, это поможет проиллюстрировать, что кэширование на стороне сервера и на стороне клиента полезно, но совершенно по-разному.

...