dataloader 的使用

过度获取问题

现在是开始谈论性能的时候了。您可能已经注意到,我们的服务器现在有多个解析函数,可以使用 MongoDB 进行数据获取。如果对10个链接进行查询,包括在每个链接上发布和投票的用户,会发生什么?这些数据将按预期的方式获取,但是由于解析函数工作的分散方式,您可能会发现服务器正在对同一数据执行多个请求!

此代码将所有请求记录到数据库服务器,并对它们进行编号,以便可以轻松地知道有多少个请求。

您应该能够看到运行服务器的终端中的日志。下面的屏幕截图显示了当数据库具有10个链接时,此查询的日志,全部由同一用户发布:

正如所看到一样,这个简单的查询触发了12个请求到 MongoDB!其中之一是获取链接数据,但所有其他数据都是相同的确切用户!这不是很好,应该能够重用已经获取的数据。这意味着在不同的解析函数调用之间处理缓存的额外逻辑…

幸运的是,对于这种问题,已经有了很好的解决方案,所以真的不需要很多额外的代码来处理这个问题。

使用数据加载器

你将要使用来自 Facebook 的工具库叫做 Dataloader。这对于避免对 MongoDB 等服务的多次请求是非常有用的。为了实现这一点,它不仅涵盖了缓存,还包括批处理请求,这也是重要的。如果测试不同的用例,那么就有不同用户发布的多个链接,就会看到单独的请求用于获取每个用户。使用 Dataloader 后,它们都将使用单个批处理请求提取给 MongoDB。

我们一步一步地浏览这个代码:

  1. 如前所述,Dataloader 也默认处理批处理,为此,当有多个项需要一起获取时被调用时需要为它提供一个批处理函数。这个加载器将被用于用户数据,这些密钥将是用户 ID。所以批处理函数只需要使用所有给定的 id 对 MongoDB 进行一次调用。
  2. 一个重要的事情是他不能用于在不同 GraphQL 请求中复用。它的缓存功能也只是短期的,以便在同义词查询中多次获取。可以通过它的文档 来了解更多。因此这个温江将返回一个用于创建数据加载器的函数,以便后来的请求使用。
  3. 最后创建用户的数据加载器,传递给批处理函数。在这里我们将使用到一个叫做 cacheKeyFn 的选项。这是因为 MongoDB 返回的用户 ids 将被作为键传递给数据加载器,实际上并不是字符串,但即使在ids相等的情况下也可能会失败的对象进行比较检查。此选项允许 统一化键,以使其可以正确的用于缓存目的。

如果尝试重新启动服务器并再次运行相同的 allLinks 查询,将清楚地看到输出的日志显示的请求数量。使用与以前相同的数据库(同一用户发布的10个链接),新的日志是:

请求数下降了75%,从12降到了3!如果认证过程通过 id 而不是电子邮件地址获取用户,则它可能只有2。但是,即使需要使用电子邮件,也可以重用数据。如果好奇的话,请查看 dataloader 中的prime 函数,这可以帮助您。

还有其他方面可以从这个服务器中的数据加载器中获益,比如获取投票和链接。对于这些步骤,您已经了解了这些步骤,所以我们不再重复。这是一个很好的机会练习更多,所以如果你愿意,请完成这些练习。

Unlock the next chapter
数据加载器的作用是?
提高解析函数代码的可读性
捕捉和处理错误
减少数据请求的数量
使数据获取调用一致