【问题标题】:Caching mechanism is not storing data in Redis缓存机制不在 Redis 中存储数据
【发布时间】:2022-01-26 00:26:00
【问题描述】:

我现在很绝望,我正在寻求任何帮助。 我正在尝试使用 GraphQL 和 Redis 在我的项目中设置缓存机制。 这就是我配置 GraphQLModule 的方式:

    GraphQLModule.forRoot({
            cache: new BaseRedisCache({
                client: new Redis({
                    host: 'localhost',
                    port: 6379,
                    password: 'Zaq1xsw@',
                }),
                cacheControl: {
                    defaultMaxAge: 10000
                },
            }),
            plugins: [
                responseCachePlugin()
            ],
            autoSchemaFile: path.resolve(__dirname, `../generated/schema.graphql`),

            installSubscriptionHandlers: true,
        }),

这就是我创建查询和突变的方式:

    @Resolver()
    export class AuthResolver {
constructor(
    private readonly prismaService: PrismaService,
    private readonly authService: AuthService,
){}

@Query(returns => String)
async testowe(@Args(`input`) input: String, @Info() info: any) {
    info.cacheControl.setCacheHint({ maxAge: 5000, scope: 'PUBLIC' });
    return 'test';
}}

当我使用 GraphQL Playground 并尝试此查询时,我得到的响应和标题如下所示:

    HTTP/1.1 200 OK
    X-Powered-By: Express
    Access-Control-Allow-Origin: *
    Content-Type: application/json; charset=utf-8
    cache-control: max-age=5000, public
    Content-Length: 28
    ETag: W/"1c-2Df/lONPXcLzs1yVERHhOmONyns"
    Date: Tue, 28 Dec 2021 21:35:11 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5

正如您所见,有一个“缓存控制”部分。 我的问题是我看不到存储在 Redis 中的任何键或值。我使用 redis-cli 工具连接到 Redis 服务器,我尝试了“KEYS ‘*’”命令。 Redis 中没有存储任何内容。

此外,我对更复杂的查询也有疑问 - 我什至没有得到带有“缓存控制”部分的标题。

你知道我在这里做错了什么吗?我应该能够通过这种方法在 Redis 中查看存储的值吗? 提前感谢您的任何建议。

【问题讨论】:

    标签: node.js graphql nestjs apollo


    【解决方案1】:

    据我所知,您没有告诉解析器将其结果存储在 Redis 中。 Apollo Server 文档对此并不十分清楚。

    我做了一个关于缓存和 graphql 的研究项目,所以请随时阅读我的​​ Medium 帖子:https://medium.com/@niels.onderbeke.no/research-project-which-is-the-best-caching-strategy-with-graphql-for-a-big-relational-database-56fedb773b97

    但是为了回答你的问题,我已经通过这种方式使用 GraphQL 实现了 Redis:

    创建一个处理缓存的函数,如下所示:

    export const globalTTL: number = 90;
    
    export const checkCache = async (
      redisClient: Redis,
      key: string,
      callback: Function,
      maxAge: number = globalTTL
    ): Promise<Object | Array<any> | number> => {
      return new Promise(async (resolve, reject) => {
        redisClient.get(key, async (err, data) => {
          if (err) return reject(err);
          if (data != null) {
            return resolve(JSON.parse(data));
            // logger.info("read from cache");
          } else {
            // logger.info("read from db");
            let newData = await callback();
            if (!newData) newData = null;
            redisClient.setex(key, maxAge, JSON.stringify(newData));
            resolve(newData);
          }
        });
      });
    };
    

    然后在你的解析器中,你可以像这样调用这个函数:

      @Query(() => [Post])
      async PostsAll(@Ctx() ctx: any, @Info() info: any) {
        const posts = await checkCache(ctx.redisClient, "allposts", async () => {
          return await this.postService.all();
        });
        return posts;
      }
    

    您必须将您的 Redis 客户端传递到 GraphQL 的上下文中,这样您就可以使用 ctx.redisClient 在解析器中访问您的客户端 ...

    这就是我通过它的方式:

      const apolloServer = new ApolloServer({
        schema,
        context: ({ req, res }) => ({
          req,
          res,
          redisClient: new Redis({
            host: "redis",
            password: process.env.REDIS_PASSWORD,
          }),
        }),
      });
    

    这样您应该能够将数据存储在 Redis 缓存中。

    您尝试的info.cacheControl.setCacheHint({ maxAge: 5000, scope: 'PUBLIC' }); 方式是在 Apollo Server 中使用另一种缓存策略。 Apollo 能够使用此信息计算缓存控制标头,但您必须设置此设置:

    const apolloServer = new ApolloServer({
        schema,
          plugins: [
            ApolloServerPluginCacheControl({
              // Cache everything for 1 hour by default.
              defaultMaxAge: 3600,
              // Send the `cache-control` response header.
              calculateHttpHeaders: true,
            }),
          ],
      });
    

    注意:您可以将默认 max-age 设置为适合您需要的值。

    希望这能解决您的问题!

    你可以在我的研究仓库中找到我的实现:https://github.com/OnderbekeNiels/research-project-3mct/tree/redis-server-cache

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 2018-02-03
      • 2021-07-02
      • 2014-11-13
      • 1970-01-01
      相关资源
      最近更新 更多