微服务架构概念问题——微服务数据和边界
Posted
技术标签:
【中文标题】微服务架构概念问题——微服务数据和边界【英文标题】:Microservice architecture conceptual problem - microservice data and boundaries 【发布时间】:2021-05-17 00:15:39 【问题描述】:我有无法解决的概念/设计问题。我将尝试在体育术语示例中进行解释,但当然同样的问题可以应用于电子商店或任何其他系统。
我想使用 API 构建 2 个“独立”微服务来执行所需的操作。服务 A 负责球员管理,服务 B 负责球队管理。
在服务 A 中,我可以进行球员训练、购买球员物品、设置球员外观等。 例如,在服务 B 中,我可以设置团队战术、雇用团队人员、设置团队外观(徽标、颜色)等。
我已经阅读了许多关于微服务的文章和主题,并在一篇文章中写道:“......关于微服务最难的部分 = 你的数据......”
我的问题来了。我应该如何以及在哪里存储玩家和团队之间的关系(将表 TeamPlayer 想象为具有 player_id、team_id 列的简单关系表)?所以这些是我的担忧:
-
表 TeamPlayer 应该是微服务 A 还是 B 的一部分?或者两个微服务应该共享同一个数据库?
如果它将是独立的数据库,并且如果我决定微服务 B 将存储此关系,我如何验证该播放器是否存在?如果有人给我发送了错误的玩家标识符怎么办?还是我需要关心?我是否需要验证玩家是否存在或者这不是微服务 B 的问题?当然,微服务 B 知道团队,所以当提供错误的团队标识符时,我可以返回错误。
我不想从微服务 B 调用微服务 A,因为那样我会将它们紧密结合在一起,并依赖从微服务 B 到微服务 A。
如果是独立数据库,我将如何读取数据?想象一下,在 UI 中,我想要团队中的球员姓名列表。微服务 B 知道团队,只是关系和微服务 A 知道名称。我是否需要至少拨打两次电话才能收集数据?
如果是共享数据库,微服务B可以直接从数据库中读取玩家的一些数据吗?我可以想象在某些情况下,由于某些访问权限等原因不应该允许这样做,但是所有这些业务逻辑都构建在微服务 A API 中,该 API 通常读取并返回有关播放器的数据。
如何以最好的方式解决这个问题? API 网关是答案还是如何以最佳方式做到这一点?
我希望能弄清楚我的担忧:)
【问题讨论】:
【参考方案1】:一般来说,微服务的正确边界不会与您在由具有外键约束的关系数据库支持的单体应用程序中使用的规范化表很好地对齐。相反,我建议让每个服务维护自己的数据视图,以查看执行其任务所需的数据(让服务发布持久的事件日志以更改它们控制写入的状态是我推荐的机制)。在您的服务 A 和 B 的概念中可能存在多个“有界上下文”:为每个有界上下文拥有一个微服务可能是有意义的。
那么考虑到这一点,什么是团队?从“将球员分配到球队”操作的角度来看,球队可能只是与某种唯一 ID 相关联的一组球员。战术和标志/颜色与该操作无关。它只需要:
存在哪些玩家(可从管理创建新玩家的服务发布的事件中得出) 创建了哪些团队(此服务可能拥有该团队,或者它可能源自管理创建团队的服务发布的事件) 哪些球员在哪些球队(该服务肯定会拥有该数据)请注意,这种方法确实会带来最终的一致性:直到从创建球员开始经过一段时间(可能很短,认为可能不到一秒)之后,才能成功将该球员分配到球队.
【讨论】:
我有一个关于微服务边界的相关问题 - 扩展上面的示例,我们将如何实现没有附加数据实体的业务功能?即它们是纯粹的业务功能。它们不读取或更新自己的数据,但它们足够广泛,可以称为单独的业务功能,因此称为不同的微服务。 这些基本上是传奇:它们协调由涉及多个服务的多个操作组成的流程。它们不是无状态的:它们仍然必须管理它们在过程中的位置(因为在微服务中,您绝对必须处理部分故障(包括提供 saga 的服务),然后(通常)重试或回滚)。该状态可能应该是某种类型的数据实体(如果没有别的,让它在可观察性方面支付一些红利)。【参考方案2】:简短的回答是 - 表 TeamPlayer 应该是微服务 A 和 B 的一部分。
为了解释,我从 Levi 的回答中借用了一句话“我建议让每个服务都维护自己的数据视图”。这才是设计微服务的正确方式。
您可以提出有关数据重复和数据一致性的问题。是的,会有数据重复,但这是设计、开发和维护微服务的架构权衡。在数据一致性方面,最终一致性应该默认模式来维护数据库状态,除非有特定的用例(例如 - 银行)具有强一致性。
希望这个答案能让您清楚简洁地了解您的设计问题。
【讨论】:
以上是关于微服务架构概念问题——微服务数据和边界的主要内容,如果未能解决你的问题,请参考以下文章