Optimization 优化SQL数据库和面向服务体系结构中的GraphQL解析器

Optimization 优化SQL数据库和面向服务体系结构中的GraphQL解析器,optimization,graphql,apollo-server,Optimization,Graphql,Apollo Server,我的公司有一个面向服务的架构。因此,我的应用程序的GraphQL服务器必须调用其他服务来满足前端的数据请求 让我们假设我的GraphQL模式定义了User类型。此类型的数据来自两个来源: 一种用户帐户服务,公开一个REST端点,用于获取用户的用户名、年龄和好友。 我的应用程序仅使用SQL数据库来存储仅与我的应用程序相关的用户相关数据:favoriteFood、favoriteSport。 让我们假设用户帐户服务的端点自动返回用户名和年龄,但您必须传递查询参数friends=true才能检索朋友数

我的公司有一个面向服务的架构。因此,我的应用程序的GraphQL服务器必须调用其他服务来满足前端的数据请求

让我们假设我的GraphQL模式定义了User类型。此类型的数据来自两个来源:

一种用户帐户服务,公开一个REST端点,用于获取用户的用户名、年龄和好友。 我的应用程序仅使用SQL数据库来存储仅与我的应用程序相关的用户相关数据:favoriteFood、favoriteSport。 让我们假设用户帐户服务的端点自动返回用户名和年龄,但您必须传递查询参数friends=true才能检索朋友数据,因为这是一个昂贵的操作

鉴于这种背景,以下查询在getUser解析器中提出了几个优化挑战:

query GetUser {
  getUser {
    username
    favoriteFood
  }
}
挑战1 当getUser解析器向用户帐户服务发出请求时,它如何知道是否也需要请求好友数据

挑战2 当解析器查询我的应用程序数据库中的其他用户数据时,它如何知道要从数据库中检索哪些字段

对于这两个挑战,我能找到的唯一解决方案是通过解析器接收的第四个info参数检查解析器中的查询。这将允许它找出是否应该在用户帐户服务的REST调用中请求朋友,并且它将能够构建正确的SELECT查询,从我的应用程序的数据库中检索所需的数据

这是正确的方法吗?这似乎是GraphQL实现必须始终运行的一个用例,因此我希望遇到一个被广泛接受的解决方案。然而,我还没有找到很多文章来说明这一点,也没有一个广泛使用的NPM模块似乎是PostGraphile的一部分,但每周只有约12k的下载量,而每周有约18.5k的下载量


因此,我担心我遗漏了一些基本的东西,关于如何做到这一点。是吗?还是检查info参数是解决这些优化挑战的正确方法?如果有问题,我使用的是Apollo Server。

如果您想根据请求的选择集修改解析器,实际上只有一种方法可以做到这一点,那就是解析请求查询的AST。根据我的经验,graphql parse resolve info是最完整的解决方案,可以减少解析的痛苦

我想这并不像你想的那么普遍,因为我想大多数人都分为两类:

框架或库的用户,如Postgraphile、Hasaura、Prisma、Join Monster等,它们至少在数据库方面为您提供了这样的优化。 用户不关心服务器端的过度抓取,只请求所有列,而不考虑选择集。 在后一种情况下,表示关联的字段被赋予它们自己的解析程序,因此除非实际请求,否则不会触发对数据库的后续调用。然后用于帮助批处理所有这些对数据库的额外调用。对于最终调用其他数据源(如RESTAPI)的字段也是如此

在这种特殊情况下,数据加载器对您帮助不大。最好的方法是为getUser提供一个解析器,用于从数据库和REST端点获取用户详细信息。然后,您可以根据请求的字段调整这些调用或完全跳过它们,因为您已经在计划这些调用。这可能会很麻烦,但会按预期工作


这种方法的替代方法是简单地获取所有内容,但使用缓存来减少对数据库和RESTAPI的调用数量。这样,您每次都将获取完整的用户,但除非缓存失效或过期,否则您将从内存中获取完整的用户。这会占用更多的内存,缓存失效总是很棘手,但它可以显著简化解析程序逻辑。

谢谢,这是一个非常有用的响应!