微服务中的多对多关联


13

我目前有两个微服务。我们称它们为AB

微服务下的数据库A具有下表:

A
|-- users

微服务下的数据库B具有下表:

B
|-- trackers

需求说明userstrackers具有多对多关系。

我不确定如何在微服务架构中正确处理此问题。

我可以看到此方法是以下三种方法之一:

  1. 一个user_trackers表添加到微服务A。这类似于包含表中的“ users和”的“外键”的联接表trackers
  2. 一个owners表添加到微服务B。该表的作用类似于多态联接表。这将允许任何服务创建与跟踪器的关联。这可能看起来像这样: B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id
  3. 为保存记录userstrackers在每个微服务。使它们与某种pubsub系统保持同步。

我最初打算使用选项2,因为我喜欢它保留了事务边界。我可以创建一个跟踪器并将其与某些原子关联。但是,它似乎超出了微服务的范围B。微B服务为什么要关心微服务A想要建立关联?

我觉得这里可能存在一个我不知道的好模式。我提出的任何选择是否有意义?还有另一种可能更有意义的选择吗?

Answers:


12

首先,我将从域描述开始。您没有提到它的含义(我可以猜测,但这只是一个猜测)。之后,我将尝试使用价值链分析或业务能力映射来分解它。只有在那之后,我才会考虑实施。

考虑到您的问题,我想到的第一件事是您错误地确定了服务边界,仅因为它们需要彼此的数据。您不想以分散的整体而告终,对吗?

第二件事是您可能还没有充分了解自己的域名。users表代表什么概念?是否registered user具有注册所需的所有信息和行为?您确定与之通信是正确的概念trackers吗(无论它是什么)?因此,如果我做对了,您的选择2正是关于这一点:引入与owner您的领域更接近的概念。如果确实如此,我也支持选项2。

但是,微服务B似乎超出了范围。微服务B为什么要关心微服务A要创建关联?

这都是关于边界的。我猜您想围绕实体形成微服务。这就是SOA 分层服务体系结构失败的地方。更好的方法是创建代表某些业务功能的服务,因此它们封装了数据和行为。从更实际的角度来看,它是围绕业务流程或用例创建服务。例如,您可能有一项用于用户注册的服务。它包含注册用户所需的用户数据和行为。因此,user自然而然地形成的概念,并且它仅属于服务A。这又引出了我的观点:关于服务的另一种思考方式是有界上下文。对齐服务和有限的上下文是一个好习惯。

注册用户后,UserCreated可能会发出事件。我想您的第二项服务对此很感兴趣。因此,在接收到它之后,可以创建一个完全不同的实体,例如,Owner实体(无论是哪个)。我非常确定它与tracker实体之间存在许多有趣的协作-将它们放在一个服务中。

对选项3极为谨慎。如果复制数据,则会出现功能。这导致紧密耦合。并且不要用CQRS术语来涵盖,它不是关于服务之间通过事件进行数据同步。


我喜欢“分布式整体”一词,但是在您提供的链接中定义它的方式似乎与此处的问题没有直接关系。我认为您使用它的方式与服务之间的耦合有关,本文重点介绍二进制依赖性。我认为您使用的方式更好,但是我正在努力寻找一个明确定义该方式的参考。
JimmyJames

我一直将闲聊服务包括在“分布式整体”类别中,该类别并不普遍使用。
Zapadlo

6

Zapadlo的答案中有很多很好的信息和理由。我将在此处添加一些实用建议,以使您更轻松地解决问题以及该答案中的建议。

设计问题的方式围绕数据库结构以及如何在其中适应对结构的新要求。这意味着您正在从数据模型中构建服务设计。例如,我看不到如何访问或使用用户和跟踪器之间的关系。

在服务设计中,接口的结构是设计中最重要的事情。实际上,相比而言,实现几乎是无关紧要的,尤其是在微服务的情况下。原因是,一旦将服务放置到位,对服务的所有依赖关系都应仅存在于接口上。如果您做对了,您应该可以完全重写实现,而无需任何使用者。这就是自治的主要好处。没有人关心您的构建方式。他们只需要它可以按照您所传达的方式工作即可。

在任何人都可以确定它在数据库中的外观或所需位置之前,您确实需要解释如何使用此信息。这是通过服务公开的东西,还是您想要整理以进行分析的某种数据?

附带一提,我几乎不惜一切代价避免了双向依赖。如果您有依赖关系,您真的只希望一方知道另一方。一旦在两个方向上都存在依赖关系,它们的服务就本质上成为一个原子单元。


0

其中很多归结于域本身。如果追踪者为零的用户没有意义,则用户服务需要了解追踪器。如果跟踪器必须具有用户,则跟踪器需要了解用户。如果像具有多个所有者的跟踪器或将跟踪器从一个用户转移到另一个用户这样的事情有意义,那么此信息可能属于另一种服务。


0

问题:为什么将数据与数据表分开?

我倾向于选择选项3:服务完全独立,可以回答他们可能需要回答的各个问题。此外,它们更具弹性。但是请注意,如果服务错过事件,它们可能会失去同步,但是可以通过最终的一致性来解决。

另外,您可以考虑合并两个服务-如果两个服务都无法在不了解彼此的情况下回答,那么我将合并它们,因为它们可能属于单个域。


这是微服务信仰的一部分,每个服务都需要完全自治。Thomas Erl在“服务设计原理 c 中将其描述为面向服务的原则之一。2008.
JimmyJames

@JimmyJames作为一个自己编写ms体系结构的人:关于ms应该有多大这个问题有很多争论。在这种情况下,大小甚至可能无关紧要,因为服务可能未正确分离-例如,不要沿表分割,沿业务域分割。
Christian Sauer

对。问题在于,目前围绕微服务的主要货物崇拜。我看到很多人实现微服务,因为那是很酷的孩子正在做的事情,而不是考虑或理解权衡取舍。例如,我感觉到很多人认为MS自主权与技术和“云”有关。我认为它更多地是解决组织问题的方法。取消对网络IO的交易指针的引用非常昂贵。您不能只是无所顾忌地应用它,并期望一切顺利。
JimmyJames

@JimmyJames我认为它也可能与技术有关-特别是当certian技术非常适合某些领域而不适用于其他领域时。我们为MS使用C#和Python。其中一些是由于组织问题造成的(“我已经为C#编程了20年,不需要学习新型的无类型语言!”)。-而且由于我们系统的性质。数据科学部分最好用python制作,而某些基础结构和Web任务最好用C#完成。
Christian Sauer

当然,这是一个很合理的理由。我看到的问题是,人们会希望将每个服务拆分为一个单独的节点,这仅仅是因为“我们在做微服务”,即使所有内容都是在同一平台上用相同的代码编写的,并且服务之间存在大量依赖关系。在这种情况下,微服务确实没有太多好处,并且您添加了一系列新问题。
JimmyJames
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.