Apollo Server - путаница с параметрами кэша / источника данных
Документы ( https://www.apollographql.com/docs/apollo-server/features/data-sources.html) показывают такой код:
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 ответ
cache
перешел к ApolloServer
насколько мне известно, строго используется в контексте RESTDataSource
, При извлечении ресурсов из конечной точки REST сервер проверяет Cache-Control
заголовок в ответе, и если он существует, будет кэшировать ресурс соответствующим образом. Это означает, что если заголовок max-age=86400
ответ будет кэширован с TTL 24 часа, и, пока не истечет срок действия записи в кэше, он будет использоваться вместо вызова того же URL-адреса REST.
Это отличается от механизма кэширования, который вы реализовали, поскольку ваш код кэширует ответ из базы данных. Их цель одинакова, но они работают с разными ресурсами. Единственный способ, которым ваш код будет эффективно дублировать то, что ApolloServer cache
уже делает, если вы написали подобное DataSource
вместо конечной точки REST.
Хотя оба этих кэша сокращают время, необходимое для обработки вашего ответа на GraphQL (выборка из кэша заметно быстрее, чем из базы данных), кэширование на стороне клиента уменьшает количество запросов, которые должны быть отправлены на ваш сервер. В частности, InMemoryCache
позволяет повторно использовать один запрос в разных местах на вашем сайте (например, в различных компонентах React), получая запрос только один раз.
Поскольку кэш на стороне клиента нормализован, это также означает, что если ресурс уже кэшируется при извлечении через один запрос, вы можете избежать его повторного получения, когда он запрашивается другим запросом. Например, если вы извлекаете список пользователей с одним запросом, а затем извлекаете пользователя с другим запросом, ваш клиент может быть настроен на поиск пользователя в кэше вместо выполнения второго запроса.
Важно отметить, что, хотя ресурсы, кэшированные на стороне сервера, обычно имеют TTL, InMemoryCache
не. Вместо этого он использует "политики выборки" для определения поведения отдельных запросов. Это позволяет вам, например, иметь запрос, который всегда выбирается с сервера, независимо от того, что находится в кэше.
Надеюсь, это поможет проиллюстрировать, что кэширование на стороне сервера и на стороне клиента полезно, но совершенно по-разному.