微服务应该互相交谈吗?


30

我正在设计使用微服务的应用程序,但不确定使用哪种最佳机制从多个服务收集数据。

我相信有两种选择:

  • 集成了“服务间”通信机制,该机制允许服务直接对话。在将合并的响应返回给API网关之前,API网关将调用单个服务,然后再调用其他服务来收集数据。然后,API将响应返回给调用方。(当对serviceB的调用需要serviceA的响应时,这必须是同步调用。IE单独的人和地址服务。)
  • 让API网关直接调用每个服务,并在返回响应之前合并API中的数据。

我倾向于第二种选择,因为使服务彼此交谈会引入耦合,在这种情况下,我最好还是构建一个整体应用程序。但是,使用此选项时,我可以想到一些严重的缺点:

  • 让API执行对多个服务的多次调用会增加API服务器的负载,尤其是在其中某些调用处于阻塞状态时。

  • 这种方法意味着API必须“知道”应用程序正在尝试做什么(IE Logic必须被编程到API中才能依次处理调用服务,然后合并数据),而不仅仅是充当微服务的愚蠢“终点”。

我想知道解决此问题的标准方法是什么,是否还有我遗漏的第三种选择?


你能提供一些背景吗?您的应用是什么,它打算做什么
Ewan 2016年

我的猜测是介于这两个选项之间:每个微服务都需要根据其工作与其他微服务进行通信。API网关也可以被视为微服务,主要将工作委托给其他服务。
Bart van Ingen Schenau,2016年

我认为在服务器端组成微服务会破坏开始使用微服务的主要目的。整个想法是使服务独立,并将编排交给客户。但也许我不切实际
Sridhar Sarnobat

Answers:


21

我通常建议不要让微服务彼此进行同步通信,最大的问题是耦合,这意味着服务现在已经相互耦合,如果其中一个服务失败,则第二个服务现在会完全或部分失效。

我将在状态更改操作和读取操作(CQS 命令查询分离)之间做出明确区分。对于状态更改操作,我将使用某种消息传递基础结构,以免失火。对于查询,您将使用同步请求响应通信,并且可以使用http API或直接进入数据存储。

如果您正在使用消息传递,则还可以查看发布订阅以在服务之间引发事件。

要考虑的另一点是(事务性)数据共享(与只读视图相对),如果您公开内部状态,则读取器可能会获得错误的数据状态或错误的版本,并且还可能锁定数据?

最后但并非最不重要的一点是,请尽一切可能使服务保持自治(至少在逻辑级别上)。

希望这是有道理的。


11

这取决于您为什么需要该数据。如果它是用于UI的,那将是完美的选择。而且,这就是应该的方式。克里斯•理查森(Chris Richardson)对这个概念有很好的解释,萨姆•纽曼(Sam Newman)关于相似概念的一篇很棒的文章叫做“ 后端的前端”

但是,如果出于某种逻辑需要它,则很有可能服务边界是错误的。

常识告诉我们我们的服务应该具有几个特征。他们是:

  1. 低耦合。如果您对服务A进行了某些更改,则您不希望它们影响服务B。
  2. 高凝聚力。如果需要实现某些功能,则希望受影响的服务数量最少。
  3. 高度自治。如果某些服务失败,则您不希望整个系统宕机。
  4. 正确的粒度。您不希望您的服务过于闲谈,因为您的网络更加复杂比您想象得多。
  5. 服务应通过事件进行通信。您不希望您的服务彼此了解,因为它会降低可维护性。考虑一下如果需要添加新服务会发生什么。
  6. 分散的数据。服务不应共享信息的存储方式。就像一个好的对象一样,它公开的是行为,而不是数据。
  7. 服务编排而非编排。

为了实现这一目标,请将您的服务边界视为业务能力。标识服务边界的正式过程如下所示:

  1. 确定更高层次的边界。我喜欢将它们视为您的组织应实现其业务目标并获得其业务价值的步骤。您可以通过了解波特的价值链来了解基本步骤的想法。
  2. 在每个服务中,进行更深入的研究。确定有自己职责的儿童独立单位。
  3. 注意他们的沟通方式。正确的服务主要通过事件进行通信。考虑一下您的组织结构。它们内部的通信非常密集,尽管通常会暴露一些外部事件。

应用此方法的一个示例可能会引起一些关注。


1

默认情况下,我也倾向于第二种方法,尽管可能不在您的“ API网关”中,但是我认为创建一个新的微服务是完全合理的,其唯一目的是协调对其他微服务的请求并代表以更高级别的形式显示数据。在微服务体系结构中,我倾向于让“基础”微服务直接相互通信。

为了使这一点更加主观,假设一个服务依赖于另一个服务如果第一个服务需要直接或间接来自第二个服务的数据或服务。用数学术语来说,我们希望这种关系是偏序而不是preorder。在图表形式中,如果绘制了依赖图,则应该获得一个 Hasse图并且没有任何(定向)循环。(在Hasse图中,边缘从下到上隐式指向。)作为进一步的指导原则,您希望从顶部到底部的路径通常更短。这意味着默认情况下您想更直接地依赖事物。原因是这样可以最大程度地减少因任何特定请求而可能出错的事件的数量,最小化开销并降低复杂性。因此,在此度量标准的“理想”情况下,Hasse图将只有两个级别。当然,您可能有很多原因想要引入中间服务,例如缓存,合并,负载平衡,故障管理。

要详细说明让API网关“智能”的第二个方面,现在FalcorRelay / GraphQL之类的框架正在吸引人们的注意是一种模式,它可以请求更多操作规范,以便“ API网关”可以通用执行这些规范,而不必知道GetTimeline需要什么。取而代之的是,它将收到诸如“从用户服务请求此用户信息,并从邮政服务获取这些帖子”之类的请求。


0

我怀疑您对服务进行“呼入”的需求表明您正在使用一个体系结构尚未完善的系统,因为这种对微服务进行“呼入”的需求是一种耦合形式,这种情况很少出现微服务是经过适当设计的。

您能否进一步说明您要解决的问题?用简单的英语?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.