【问题标题】:Invoking dependent microservice调用依赖微服务
【发布时间】:2019-04-01 03:11:42
【问题描述】:

假设我有 2 个微服务:Service1 和 Service2。他们每个人都有自己的数据库。 Service1 有 EntityA,Service2 有 EntityB

EntityA {
    Long id;
    //other fields
    EntityB entity;
}

EntityB{
     //other fields
}

我正在使用 Spring 的 RestTemplate 来检索和保存数据。问题是:当从 Service1 的数据库中检索 EntityA 时,我没有 EntityB 的数据,因为它们保存在 Service2 的数据库中,我知道我应该通过 RestTemplate 进行休息调用以从 Service2 的数据库中检索 EntityB,但是两者之间的关系呢?实体 - EntityA 是否应该仍然在其中包含整个 EntityB 对象,即使它的字段大部分时间都是空的,除了 id ?我错过了什么? 先感谢您。

【问题讨论】:

    标签: java spring web-services microservices


    【解决方案1】:

    我遇到了这种模式,我认为它对您的情况很有用。
    该模式称为CQRS(Command Query Responsibility Segregation,一口)

    该模式假设您有一个事件溯源系统,自从您使用微服务以来,您已经有了很大的变化。

    Service1 中的任何 EntityA 发生更改时,Service1 会发布一个事件。 Service2 也是如此,当任何 EntityB si 发生变化时,它也会发布一个事件。

    然后我们有 Service3 订阅来自 Service1 的事件,而 Service2 聚合数据并将其存储在其本地数据库中。现在您所要做的就是调用 Service3Service1Service2 获取聚合数据。

    当然,这种模式有其缺点,例如最终一致性,但在某些情况下,它实际上可能是最合适的。

    这个想法主要来自这里:https://microservices.io/patterns/data/cqrs.html。 我还会从这里至少阅读“何时使用此模式”部分:https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs

    【讨论】:

      【解决方案2】:

      从技术角度来看,您的问题可以通过API Gateway 解决。

      简而言之,您应该定义一个新的微服务,例如 gateway service,它将由您的 API 客户端调用。然后gateway service 会:

      1. 调用Service1 以获取Entity1 以及id 以获取Entity2
      2. 根据步骤 1 中的 id 调用 Service2 以获取 Entity2
      3. 聚合两个响应(在您的情况下,在 Entity1 中设置 Entity2 值)。
      4. 将聚合响应返回给客户端。

      设计时要记住两件事:

      • 您的 API 客户端不应该知道他的数据是由两个服务获取的。
      • 在网关中聚合客户端响应通常更干净,因为它允许在微服务之间进行更高级别的解耦。例如,您可以按如下方式对您的实体建模(并移除 Service1Service2 之间的数据模型依赖关系,从而允许这两个服务独立发展)。

      参见下面的 sn-p:

      // In Service1
      EntityA {
          Long bId; 
      }
      
      // In Service2
      EntityB{
      
      }
      
      // In Gateway
      Response {
          EntityA a;
          EntityB b;
      }
      

      天气Entity1 应参考Entity2 的决定不取决于您的数据分布方式,而是取决于您的业务需求。如果您有一个单体应用程序,并且在这种情况下,Entity1 引用Entity2 是有意义的,那么在微服务环境中这样做仍然有意义。

      【讨论】:

      • 谢谢 Alex,您的回答对我帮助很大。我实际上是在提取单体应用程序的一部分并使其成为微服务。这是要提取的大约 4 个微服务中的第一个。你能推荐一些与这个主题相关的阅读吗?我还有一个问题 - 当我必须在 Service1 中做出一些影响 EntityA 并且基于 EntityB 的数据的决定时,我应该怎么做?这难道不是糟糕设计的标志吗?
      • @devoxy 理想情况下,这两个微服务应该分开发展。但在实践中很少出现这种情况。一种常见的方法是通过队列集成您的微服务。例如,您可以发布与EntityB 相关的数据更改消息(来自Service2),并在Service1 中使用这些消息(您将有一些与来自Service2 的数据更改相关的逻辑)。这不一定是设计不佳的标志,但您应该评估天气是否混合了责任。我回答你的问题了吗?
      • 关于文档,API 网关模式在我的回答的链接中得到了正确的描述(至少从理论上的角度)。实用的方法在很大程度上取决于您的技术堆栈、约束等。
      • 再次感谢亚历克斯。当我写“你能推荐一些与这个主题相关的阅读材料吗?”我的意思是一些从单体应用中提取微服务的例子:)。我知道这是一项非常复杂的任务,但我找不到任何包含实际代码示例的内容,只是有关执行一般步骤的建议。
      • 抱歉,没有想到具体的内容。我知道 Spring IO 中有一个视频,其中包含一些关于将单体重构为微服务的编码,但我找不到它。
      【解决方案3】:

      我想到的两个解决方案既简单又复杂。

      重复数据

      在 MS 之间,通常有一个高度可用的 pub-sub 或消息队列集群系统。当EntityB 保存在Service2 中时,您将事件发送到队列或发布-订阅系统。 Service1 可以订阅该特定事件并将有关 EntityB 的信息存储在其自己的数据库中。

      组域逻辑

      也许,Service1Service2 的域之间的相关性太大了。 在这种情况下,您可能希望将您的服务组合成一个服务。

      【讨论】:

        猜你喜欢
        • 2015-09-03
        • 1970-01-01
        • 2020-05-21
        • 2022-01-08
        • 2021-05-12
        • 2020-12-09
        • 2017-09-08
        • 1970-01-01
        • 2018-06-07
        相关资源
        最近更新 更多