微服务关系/依赖策略

时间:2018-03-13 09:37:06

标签: architecture microservices

我希望对处理数据依赖关系和微服务关系的几种不同解决方案提供一些反馈。

考虑以下服务: enter image description here

简要说明,有银行服务和帐户服务。帐户服务持有帐户,并始终使用bankId连接到银行。

困境在于如何处理和验证这种关系以及bankId以及每个决策带来的利弊。

选项1:

完全忽略验证。对帐户的POST / PATCH永远不会验证给定的BankId是否是现有ID。

赞成

  • 服务彼此之间并不了解,并且它们之间没有硬性依赖关系,如果一个服务发生故障,另一个服务不会停止工作。 (这是一个很大的)

缺点

  • 如果BankId不正确,则帐户会丢失"并且无法访问。
  • 报告服务和/或任何读者必须对丢失或不正确的银行进行说明,并在不崩溃的情况下显示其拥有的任何数据。

反射

服务完全解耦,这将有利于性能,正常运行时间和复杂性。所有读者和应用程序都需要被反应并且#34;能够处理跨服务关系何时被打破"。

选项2:

始终使用同步REST调用进行验证。如果BankId不存在或无论如何BankService无法响应或被破坏,POST / PATCH对帐户将失败。

赞成

  • 100%数据完整性。
  • 读者不需要处理并希望破坏关系。

缺点

  • 服务紧密依赖,您可以说它们不再是适当的微服务,也可能是单一服务。
  • 表现受到负面影响
  • 如果BankService关闭,AccountService POST / PATCH将无法正常工作,GET仍然有效。

反射

服务紧密依赖,这真的很糟糕,这更像是旧的方式"一般来说,我觉得这样做是错误的。在这种情况下合并服务的情况更糟,如果你开始通过合并来解决问题,可能会继续这样做并很快就会收到大量服务,并且你已经完成了整个微服务原则。当然,阅读仍然有效,但这是一个遥不可及的借口。

选项3:

在AccountService中保留BankEntity的只读副本。 AccountService通过事件总线保持更新。在POST / PATCH上对此进行验证。

赞成

  • 100%数据完整性。
  • 读者不需要处理并希望破坏关系。
  • 没有可衡量的负面影响

缺点

  • 复杂性增加
  • 由于事件的异步性,我们不能假设银行的只读副本是100%更新的。创建BankEntity后,快速连续的POST / PATCH可能会失败。
  • AccountService获得更多其他服务的知识,即使它是一个松散的依赖

反射

这是最复杂的方式,读者不需要处理破坏的关系,并且性能/运行时间问题得到解决,但是,您必须处理以下事实:银行的只读副本可能不会尚未更新,请稍后再试。将其与选项1进行比较意味着您仍然需要以某种方式处理它,并且由于这将更加复杂,我会说它不是最有利的。

结束思考

实现的一般目标是服务不会彼此同步通信,并且数据完整性尽可能好。

然而,在微观服务架构中,我认为关系完整性可能只是你接受失败的事情之一。

我们的决定倾向于选项1,实际上只是忽略它,并且在您需要使用它的任何时候,您必须期望并处理它可能不正确。这似乎是最多的"微服务"解决方案,服务并不是真正了解彼此,唯一能做的是需要进行跨服务操作的应用程序和报告服务。

任何服务都需要承担全部责任,他们在任何时候都拥有完成自己所需的所有数据。让我们说,为了论证,AccountEntity需要一个位置,无论出于何种原因成为可用且完整的域名实体,您不能指望依赖BankId,您必须将位置存储在AccountEntity上,也许如果它改变了,你就会得到一个事件,你可以更新它。

TL; DR 您对此有何体验,意见和想法?你会怎么做?你会选择哪种策略?

2 个答案:

答案 0 :(得分:3)

首先,您选择的选项取决于您的业务需求。

  1. 完全忽略:在您的银行和帐户案例中,我不想使用此方法,因为这可能会导致帐户丢失。在业务流程确保sonner或更高版本得到解决的情况下,您可以采用这种方法。
  2. 总是验证:我不会这样做,因为这会使服务依赖。我会做什么我使用的变体:
  3.   

    **首先我会允许在没有验证的情况下创建帐户,帐户的初始状态为CREATED

         

    **现在在AccountService中创建一个侦听AccountCreated事件的ProcessManager,并在异步中使用Bank Service验证它   检查银行ID是否有效,如果是,则更新帐户状态   验证,或者如果银行ID无效,则将状态更新为INVALID BANK ID   并采取适当的行动

    1. 保持只读复制:这个我也不会这样做,因为首先需要复制大量数据,其次复制可能是陈旧的。例如:银行已删除但未知此服务或银行刚创建且未知此服务,在这两种情况下都需要额外检查和异步验证。
    2. 现在实际上所有方法都是有效的,可能取决于您的关键业务需求。有时即使创建依赖项也需要实时验证

答案 1 :(得分:0)

这个是基于意见的,这里没有正确或错误的答案(实际上不是真的,很多错误的答案,但也有很多正确的答案)。这真的取决于你的用例。就个人而言,我倾向于更松散的耦合,直到我需要更强的耦合。

我最喜欢的模式是放入银行ID而不是数字的URL。这为您提供了指向银行的指针,而无需了解其他服务的内部结构的具体细节。

如果您以后决定需要该ID,则可以随时解析所有URL,并收集ID,或者您可以在运行时执行此操作。重点是,您还不必知道这一点,在您使用这些数据的用例之前,请不要将它结合起来。