微服务架构:跨服务数据共享

30
考虑以下与在线商店项目相关的微服务: 用户服务保存商店用户的帐户数据(包括名、姓、电子邮件地址等)。 购买服务跟踪有关用户购买的详细信息。
每个服务都提供了一个用于查看和管理其相关实体的用户界面。购买服务索引页面列出了购买内容。每个购买项目应具有以下字段:
id,购买用户的全名,购买物品的标题和价格。
此外,作为索引页面的一部分,我想添加一个搜索框,让商店经理按购买用户名搜索购买。
对于购买服务不持有的数据如何获取不是很清楚-例如:用户的全名。 当尝试执行更复杂的操作(例如按购买用户名搜索购买)时,问题变得更加严重。
我想可以通过在用户创建时广播某种事件来解决这个问题(并仅在购买服务端保存相关用户属性)。在我看来,这远非理想。如果您有数百万用户,该怎么办?您会在每个消耗用户数据的服务中创建数百万条记录吗?
另一个明显的选项是在用户服务端暴露API,根据给定的ID返回用户详细信息。也就是说,在购买服务中的每个页面加载中,我将不得不调用用户服务以获取正确的用户名。虽然不理想,但我可以接受。
那么如何基于用户名实现购买搜索呢?嗯,我总是可以在用户服务端公开另一个API端点,该端点接收查询术语,在用户服务中对用户名执行文本搜索,然后返回与条件匹配的所有用户详细信息。在购买服务中,将相关ID映射回正确的名称并在页面上显示它们。这种方法也并不理想。
我错过了什么吗?是否有其他方法来实现上述目标?也许我面临这个问题就是一种代码异味?希望听到其他解决方案。

我对这个问题有点困惑。前端应用程序应该与服务分开。您应该能够在不更改服务的情况下进行前端应用程序更改。对于购买屏幕,应调用购买服务和用户服务以获取屏幕数据。或者可以在服务之前放置一个单独的API,该API将调用两个服务,然后将数据返回到屏幕。请查看此处的图表,其中显示了它应该如何工作:http://martinfowler.com/articles/microservices.html#DecentralizedDataManagement - Wayne Ellery
这是API模式的链接:http://microservices.io/patterns/apigateway.html - Wayne Ellery
我非常困惑,简直无法相信已经过去将近8年了。 - WestFarmer
4个回答

19

当涉及到微服务时,这似乎是一个非常常见和核心的问题。我希望有一个好的答案 :-)

关于这里已经提到的建议模式,我会使用“数据去规范化”而不是“多语言持久化”一词,因为它并不一定需要在不同的持久化技术中进行。重点是每个服务处理自己的数据。是的,你会有数据重复,并且通常需要某种事件总线来在服务之间共享数据。

还有另一种选择,这是对第一种选择的一种方式——将搜索本身作为一个单独的服务。

因此,在您的示例中,您有用于管理用户的“用户服务”。购买服务管理购买。每个服务都处理自己的数据,只处理所需的数据(因此,例如,购买服务不真正需要用户名,只需要ID)。然后您有第三个服务——搜索服务——它消耗其他服务产生的数据,并从组合数据中创建搜索“视图”。


4
在不同的数据库中保存适当的数据是可以接受的,这被称为多语言持久化。是的,您希望将用户数据和购买数据分开存储,并使用消息队列进行同步。对我来说,数百万用户似乎没问题,这是可扩展性问题,而不是设计问题 ;-)
在搜索时,您可能希望搜索更多内容而不仅仅是用户名,对吗?因此,如果您使用消息队列在服务之间更新数据,还可以轻松地将此数据路由到ElasticSearch等搜索引擎。从ElasticSearch的角度来看,索引哪个字段并不重要-用户名还是产品标题都可以。

1
我通常会使用这两种方法。有时候我会有另一个服务,位于 x 个其他服务之上并组合数据。我不是很喜欢这种方法,因为它会导致服务之间的依赖性和耦合度。因此,总的来说,在我的最近几个项目中,我们尝试坚持多语言持久化策略。
同时还要考虑一下,如果您需要在某种中间件服务中使用 x 个子 HTTP 请求来组合数据,那么它将导致较高的延迟。我们总是尽量减少一个任务的请求量,并尽可能通过异步队列处理所有可行的内容。(特别是数据同步)

0

如果您将模块概念化为数据的所有者和控制器,则您的模型还必须将该数据从该模块传递给其他人。相比之下,制造过程中的模块可以访问更改数据而无需拥有和控制它。

微服务是一种分布式处理架构,类似于大多数代码,其中模块传递数据以进行处理。根据哈佛商业评论和麦肯锡关于拥有供应链成员的主题的经典文章,我确定了由此模型引起的复杂性,并撰写了一篇教导程序员所需知识的文章:http://www.powersemantics.com/p.html

制造是一种集成处理架构,其中模块在不传递数据的情况下对其进行处理。这可以通过配置模块以访问相同的内存、文件或数据库表来实现。我的架构展示了如何通过引用属性在内存上实现此目标。

当您考虑“在用户服务端公开API,根据给定的ID返回用户详细信息”时,需要注意这会创建HBR所称的“不可逆转”的复杂性,我将其称为集中化复杂性。不要构建A->B(分布式)系统,因为在未能分离需求后,您无法将其去中心化。生产过程中的需求代表用户指令,而集中化模块只能让您更改错误的用户流程。换句话说,集中化模块不记录用户组或将其与派生产品用户区分开来。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接