SOA 和共享数据库

Posted

技术标签:

【中文标题】SOA 和共享数据库【英文标题】:SOA and shared databases 【发布时间】:2011-12-30 05:26:28 【问题描述】:

我不懂 SOA(面向服务的架构)和数据库。虽然我被 SOA 概念(将可重用的业务逻辑封装到服务中)所吸引,但如果其他服务/系统需要封装在服务中的数据表,我无法弄清楚它应该如何工作——或者 SOA 是否适合 完全在这种情况下?

更具体地说,假设我有两个服务:

CustomerService:包含我的Customers 数据库表和相关的业务逻辑。 OrderService:包含我的 Orders 表和逻辑。

现在,如果我需要使用 SQL 语句对 JOIN CustomersOrders 表进行处理,该怎么办?如果表包含数百万个条目,那么如果我必须使用 SOAP/XML 通过网络发送数据,则会导致无法接受的性能。以及如何执行JOIN

做了一些研究,我找到了一些建议的解决方案:

Use replication 在需要的地方制作所需数据的本地副本。但是没有封装,那么使用 SOA 有什么意义呢?对此进行了讨论 on ***,但没有明确的共识。 设置Master Data Service 封装所有数据库数据。我猜它会变得非常大(每个存储过程基本上只有一个 API 调用)并且需要一直更新。在我看来,这似乎与 enterprise data bus 概念有关。

如果您对此有任何意见,请告诉我。

【问题讨论】:

您的编辑绝对是零意义。 RESTful 服务是 API 设计的问题,拥有单独的服务实际上会将事情推向 SOA。所以你关于从 SOA 迁移到 REST 的评论类似于说从吃香蕉到使用闹钟。 感谢您的意见,但不确定我是否同意。自从面向服务架构 (SOA) 演变的曙光开始,SOA 就与 RESTful 接口的模型进行了比较和对比。 SearchSOA – Gruber 24 分钟前 另请查看:martinfowler.com/articles/enterpriseREST.html#bounded-contexts 一些 good info 关于 ROA(面向 Restful 的架构)与 SOA 的对比。 【参考方案1】:

在这种情况下,“服务”的定义原则之一是它绝对拥有它负责的区域中的数据以及对该数据的操作。

通过复制或任何其他机制复制数据,可以免除该责任。要么您也复制业务规则,要么您最终会陷入需要更新其他服务以更改您的内部规则的情况。

使用单一数据服务只是“不要做 SOA”;如果您只有一个地方来管理所有数据,那么您就没有独立的服务,您只有一项服务。

我建议改为第三种选择:使用组合将这些数据放在一起,完全避免数据库级别的 JOIN 操作。

与其考虑需要在数据库中将这两个值连接在一起,不如考虑如何在边缘将它们组合在一起:

当您为客户呈现 HTML 页面时,您可以从多个服务中提供 HTML 并在视觉上将它们组合在一起:客户详细信息来自客户服务,订单详细信息来自订单服务。

同样是发票电子邮件:可视化组合从多个服务提供的数据,无需数据库内连接。

这有两个好处:一,你不需要加入数据库,甚至不需要将数据存储在同类型的数据库中。现在每个服务都可以使用最适合他们需要的任何数据存储。

第二,您可以更轻松地更改应用程序的外部。如果您有小型的可组合部件,您可以轻松添加以新方式重新排列部件。

【讨论】:

在寻找线索时,我没有想到你的想法——这是一种有趣的方法。如果我可以消除对JOIN 的需要,就不会出现最初的问题。但是,就我而言,JOIN 似乎很难回避,因为它不是用于演示目的。但我会考虑一下。您指出的重要一点是服务应该拥有自己的数据和相关操作。 other threads 对此存在分歧。感谢您的回复! Udi Dahan 在这里有一个博客:udidahan.com - 他的工作在塑造我对该主题的看法方面非常宝贵,您会在那里找到更多有价值的信息。 您是说客户服务只能访问客户数据,而订单服务只能访问订单数据吗?我没有在 Thomas Erl 的书中看到任何提及这一点?请提供参考资料吗? @PaulTDavies 我现在没有什么具体的书籍可以推荐,但msdn.microsoft.com/en-us/library/ms954587 是对我的观点来源的可靠总结。具体来说,请参阅“外部数据”与“内部数据”讨论。 @DanielPittman 这种方法的一个问题:如果我想搜索一组连接的结果,过滤两个表中的字段怎么办。例如:查找所有来自柴郡客户的超过 100 英镑的订单?使用组合方法,我必须从 Order 服务中找到所有超过 100 英镑的订单,并从客户服务中找到来自 Cheshire 的所有客户,然后使用组合服务找到交集。与使用数据库 JOIN 相比,订单和客户的集合会大得多,并且性能会大大降低。【参考方案2】:

指导原则是缓存不可变数据就可以了 这意味着来自客户实体的简单不可变数据可以存在于订单服务中,并且无需每次需要信息时都去客户服务。将所有内容中断为隔离服务,然后总是进行这些远程过程调用会忽略fallacies of distributed computing。 如果您有广泛的报告需求,则需要创建附加服务。我称之为聚合报告服务,它再次获取用于报告目的的只读数据。可以看几年前的一篇文章I wrote about that for InfoQ

【讨论】:

我读了你的文章。伟大的阅读。我想缓存其他服务的数据与您描述的事件驱动机制相结合会起作用。对于数据不经常更改的服务,我认为我可以让服务每晚更新一次缓存,这样可以消除事件处理的复杂性。 您可能想查看互补模式,例如 CQRS martinfowler.com/bliki/CQRS.html【参考方案3】:

在您引用的 SO 问题中,许多人表示服务可以访问另一个服务数据,因此 Order 服务可以具有 GetAllWithCustomer 功能,该功能将返回所有订单以及该订单的客户详细信息.

另外,我的这个问题可能会有所帮助:

https://softwareengineering.stackexchange.com/questions/115958/is-it-bad-practice-for-services-to-share-a-database-in-soa

【讨论】:

谢谢。似乎人们对此有不同的看法。例如,如果我将CustomerService 的数据表Customers(出于性能原因)复制到OrderService,如果Customers 的设计需要更改,我最终会遇到“意大利面条”问题---我然后必须更新OrderService 的代码。而对于 SOA,这就是我想要摆脱的。 @user1035411 我认为您不应该复制数据。我只是认为应该允许订单服务访问客户服务的数据。要考虑的另一件事是,您可能需要 Order 服务的客户表,其中包含仅与订单服务相关的客户数据。客户名称将被许多服务使用,因此将保留在客户中。但是信用额度可能是订单服务的候选者?这将防止客户的设计过于频繁地更改。 我想尊重 SOA 的原则,即服务只通过它们的接口进行通信,所以如果一个服务在内部发生变化,我永远不必更新其他服务。我同意您的观点,服务可能需要存储其他服务的数据。问题在于性能以及如何使缓存的数据保持最新。通过 SOAP/XML 获取大量数据会产生沉重的网络负载,而复制通常非常顺利。由于复制违反了 SOA 原则,我想尝试另一种方式,并且按照您的建议,只存储最少量的数据。 @user1035411 我并不是说一个服务应该被允许存储另一个服务的数据,而是它可以直接访问另一个服务的数据库。有些人可能不同意,但对此意见分歧,在你的情况下,我没有看到另一种有效的方法。

以上是关于SOA 和共享数据库的主要内容,如果未能解决你的问题,请参考以下文章

2019 上半年信息系统项目管理师上午综合知识真题

SOA 服务架构之简介及理解

基于ActiveMQ的企业级SOA解决方案与源代码实战

简述我的SOA服务治理

中台服务架构的一点思考

架构杂谈