如何合并/ consolida多个RESTful微服务的响应?

11
假设有两个(或多个)提供JSON的RESTful微服务。服务A存储用户信息(姓名、登录名、密码等),服务B存储发送给/来自该用户的消息(例如,sender_id、subject、body、rcpt_ids)。在/profile/{user_id}上响应的服务A可以返回:{id:1,name:'Bob'},{id:2,name:'Alice'},{id:3,name:'Sue'}等。在/user/{user_id}/messages上响应的服务B返回一个列表,其中包含那些针对{user_id}的消息,如下所示:{id:1,subj:'Hey',body:'Lorem ipsum',sender_id:2,rcpt_ids:[1,3]},{id:2,subj:'Test',body:'blah blah',sender_id:3,rcpt_ids:[1]}。
客户端应用程序如何处理这些服务,以便将姓名显示而不是发送者/接收者ID?方法1:获取消息列表,然后开始为列在sender_id和rcpt_ids中的每个ID提取配置文件信息?这可能需要数百个请求,可能需要一段时间。相当幼稚和低效,并且可能无法扩展到复杂的应用程序。 方法2:获取消息列表,提取所有用户ID,并为所有相关用户单独进行批量请求...这假设存在这样的服务端点。在获取消息列表、提取用户ID、发送批量用户信息请求之间仍存在延迟,然后等待批量用户信息响应。
理想情况下,我想一次性提供完整的响应集(消息和用户信息)。我的研究将我带到了在服务层合并响应的方法...即API网关技术。
但是如何实现这一点呢?我可以获取消息列表,提取用户ID,在幕后进行调用并获取用户数据,合并结果集,然后提供这个最终结果...这在幕后有2个服务时可以正常工作...但是如果消息列表依赖于更多的服务怎么办?如果我需要根据二级(三级?)结果查询更多的服务,进一步解析这些响应,然后最终合并...这种疯狂会在哪里停止?这将如何影响响应时间?
我现在实际上创建了另一个“客户端”,将所有微服务响应组合成一个超级响应...这与上述方法1没有什么区别...除了在服务器级别。

这就是在"真实世界"中的做法吗?有什么见解吗?是否有任何基于这种API网关架构构建的开源项目我可以查看?

4个回答

8
我们用于解决这个问题的方案是对数据和事件进行去规范化更新。基本上,微服务需要预先从其他微服务获取其所需的数据子集,以便在运行时不必调用它们。通过事件管理这些数据。其他更新过的微服务会触发一个带有id作为上下文的事件,任何对其感兴趣的微服务都可以消费它。这样数据保持同步(当然需要一些形式的事件失败机制)。这看起来很费力,但有助于我们在未来做出有关从不同微服务中合并数据的任何决策。我们的微服务将始终具有所有可用于处理任何请求的数据,而无需同步依赖其他服务。
在您的情况下,即显示带有消息的名称,您可以在Service(B)中保留一个额外的名称属性。因此,每当Service(A)中的名称更新时,它将使用更新事件并带有更新名称的ID。然后,Service(B)消耗该事件,从Service(A)获取相关数据并更新其数据库。这种方式即使Service(A)关闭,Service(B)也将正常工作,尽管存在一些陈旧的数据,但当Service(A)启动时,它们最终将保持一致,并且您始终会在UI上显示一些名称。
参考链接:https://enterprisecraftsmanship.com/2017/07/05/how-to-request-information-from-multiple-microservices/

是的。人们经常忘记微服务的一个理想属性,那就是它们应该被设计成自主运行,即能够在不与其他服务交互的情况下尽可能实现其目的(在 OP 的示例中,提供一个消息列表以供阅读)。实现这个属性往往包括数据的复制。我喜欢称之为“本地缓存”,尽管它通常保存在数据库中而不是缓存中,因为它会提醒人们这不是应该修改的数据,除非来自拥有数据的服务的更新事件到达。 - Graham Lea

3
你需要编写另一个名为聚合器(Aggregator)的服务,该服务将内部调用这两个服务并获取响应,然后合并/过滤它们并返回所需结果。在Spring Reactive中,可以使用Mono/Flux轻松实现非阻塞。

enter image description here

一个API网关通常会进行API组合。
但这是一个典型的工程问题,你需要使用实现服务模式的微服务来实现数据库。
API组合和命令查询责任分离(CQRS)模式是实现查询的有用方式。

3

1
这是一个示例:https://github.com/lreb/netcore-microservice-ocelot - Luis Raúl Espinoza Barboza

1
理想情况下,我希望一次性提供完整的响应集(消息和用户信息)。
你所描述的问题是 Facebook 多年前意识到的问题,他们决定通过创建一个名为 GraphQL 的开源规范来解决这个问题。
但是,如何实现呢?
它已经在各种流行的编程语言中实现了,也许你可以在自己选择的编程语言中尝试一下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接