首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Apollo联合配置访问其他服务的子服务数据

使用Apollo联合配置访问其他服务的子服务数据
EN

Stack Overflow用户
提问于 2021-03-06 01:24:23
回答 1查看 450关注 0票数 1

我们已经使用Apollo Federation作为我们的主要api大约有1.5年了。在联合网关后面是6个子graphql服务,它们都在网关处组合在一起。当您有一个跨越不同服务的结果数据集时,这种配置真的很好。例如,引用所购买的用户以及与其相关联的事件的门票列表等。

我们经历过这种崩溃的一个地方是,当需要在另一个子服务(或跨其他子服务)(解析器/路径)中定义的预先设置的数据时。(我们已经发现)没有办法从子服务中查询联合来获取联合数据集,以便解析器使用这些数据。

例如,假设我们定义了一个graphql查询,用于查询事件的所有门票,并通过联合返回购买者数据、事件数据和产品数据。如果我需要来自解析器的数据集,我将需要自己再次执行所有这些查询,复制dataSource逻辑,并必须在代码中匹配数据。

出现了一个疯狂的想法,就是将apollo-datasource-rest dataSource设置为对我们的网关端点进行查询,作为我们解析器的dataSource。这样我们就可以请求我们需要的数据,并让Apollo Federation按照设计的方式将所有数据缝合在一起。因此,我们将从已经定义此查询的graphql网关请求数据,而不是由解析器在数据库中查询所有不同的数据片段,然后将它们匹配起来。

我们试图通过这样做来避免在子服务中有一组重复的查询,以获取在其他服务(或跨服务)中已经可用的详细信息。

问题是

这真的是个坏主意吗?

这是一个看似合理的想法吗?

以前有没有人尝试过这样的东西?

是的,我们必须确保解析器上没有循环依赖。在我们的例子中,我看到了在突变中收集初始数据时使用的"dataSource访问网关“。

联邦查询示例。在此查询中,eventallocatedTopurchasedByproduct都是其他服务中的类型。event是事件类型,allocatedTopurchasedBy是Profile类型,product是Product类型。此查询为我提供了用于向结果集中的人员发送电子邮件通知的所有数据。不过,要从一个解析器获得这些数据,在一个突变中排队这些电子邮件意味着我需要进行许多查询,并通过自己的代码对齐所有数据,而不是使用Gateway/federation,后者已经对已经建立的查询执行了这一操作。关于使用apollo-datasource-rest查询我们自己的网关的想法是以这种形式获取这些数据。而不是通过单独的查询和代码来对齐id等。

代码语言:javascript
复制
query getRegisteredUsers($eventId: ID!) {
  communications {
    event(eventId: $eventId) {
      registered {
        event {
          name
        }
        isAllocated,
        hasCheckedIn,
        lastUpdatedAt,
        allocatedTo {
          firstName
          lastName
          email
        }
        purchasedBy {
          id
          firstName
          lastName
        }
        product {
          __typename
          ...on Ticket {
            id
            name
          }
        }
      }
    }
  }
}
EN

回答 1

Stack Overflow用户

发布于 2021-03-06 10:42:35

仅供参考,我不太理解这个问题,直到我看了你的编辑,其中有一些例子。

这真的是个坏主意吗?

根据我的经验,是的。不是作为一个想法,因为你和其他非常聪明的人一起做了这件事。

这是一个合理的想法吗?

这绝对是合理的,但我不推荐这样做。

以前有没有人尝试过这样的东西?

是的,但我希望你不会。

你的问题

让解析器向网关发回请求:

我不推荐这样做。我亲眼目睹了这种情况的发生,我个人也曾努力帮助公司走出这一困境。循环依赖将会发生。当你有越来越多的跳跃、TLS握手等等时,延迟就会直线上升。引入非GraphQL感觉很奇怪,但最终它比“只与网关对话”的方式更简单、更快、更易维护。

然后呢?

当您处理一些突变时,需要来自多个数据源的数据才能处理单个事件(例如向个人发送事务电子邮件),您有一些选择。帮助我弄清楚这一点的是一个问题:“在GraphQL之前,我会如何做到这一点?”

你有一个单独的“编排服务”,它接受突变并进行调用(最好是非图形so,所以REST,gRPC,

  1. Orchestration:?)发送到所有者服务以收集数据。编排层不拥有数据,但它可以与其他服务通信。它类似于联邦,但用于将数据发送到请求中,而不是发送到响应中。

  1. Choreography:您可以触发大致相同的事情,但通过事件流。(不适用于GraphQL的请求/响应模型)

  1. CQRS (projections):数据库数据的副本,用于报告之类的事情。CQRS基本上是“你读取数据的方式不必与你写数据的方式相同”,它允许像事件源数据这样的东西。如果您的所有数据源实际上共享同一个数据库,那么您甚至不需要“投影”,因为您只需要一个读取的副本。如果您的规模不足以复制副本,只需跳过它,并承诺永远不会写入当前域不拥有的数据。

我做了什么

在我工作的地方,我让我们达到了:

查询

  1. 查询总是以“一次数据库调用”开始。
  2. 如果“一次数据库调用”进入一个数据域(通常为真),则该查询进入一个服务,并且联合身份验证填充树的叶子。
  3. 如果你的“一个数据库调用”需要跨域的数据(例如,获取所有包含产品X的订单,但按客户的名字排序),你需要一个数据库投影。这最好可以由一个“报告服务”来处理:它不拥有任何数据,但它读取所有数据。

突变

  1. 如果您的顶级突变只修改了一个域内的行为,突变进入服务,它可以使用数据库事务,并且联合填充叶
  2. 如果您的突变需要跨多个域写入并需要立即保持一致性(使用库存、付款等下单),我们选择编排来跨多个服务写入(必要时回滚,因为我们没有数据库事务为我们做这件事)。
  3. 如果您的突变需要来自多个位置的数据进一步发送到请求中(如发送电子邮件),我们选择了编排来从多个服务中提取数据,并将其向下推送。这感觉非常像联邦,但与之相反。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66496933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档