面向服务的体系结构和松散耦合与SQL JOINS

时间:2013-03-31 14:57:41

标签: web-services data-mining soa

让我们假设我们有一个类似于下面绘制的SOA基础架构 每个服务都可以在不同的主机上运行(这对于两个额外的网络服务“网站”和“支付系统”特别有效。)

SOA infrastructure

显然,我们有一个数据(持久性)层。假设它是通过EJB + JPA或类似的东西实现的。

如果我们想在不同的服务之间加入数据(在用户界面中),我至少会看到几种选择:

  • 我们希望在RDBMS级别进行高效的JOIN,因此我们有一个包(即.persistence.package)包含所有实体和会话外观(CRUD实现),这在某种程度上必须为每个服务共享(如何?)。也就是说,如果我在订单模式中更改某些内容,我必须重新部署这些包,引入几乎所有内容之间的紧密耦合。此外,数据库必须是唯一的并且是共享的。

  • 为了避免这些问题,我们为每个不同的服务(即order.package)保留一个实体包,让服务通过一些协议(soap,rest,esb等)进行通信。所以我们可以在每个主机中本地保存数据(不共享任何架构),我们不需要重新部署实体包。但是这种方法对于数据挖掘来说非常糟糕,因为必须在多个服务之间搜索和返回相关数据的查询将非常效率低下(因为我们无法进行SQL连接)

对于上述问题,是否有更好/标准的方法?

2 个答案:

答案 0 :(得分:4)

SOA的主要动机是可以单独更改的独立组件。正如Marco提到的那样,次要动机是将系统简化为更容易解决的小问题。 不同服务的优点是灵活性,缺点是更多的管理和开销 - 这种开销应该通过你得到的东西来证明 - 例如,我发布了一个名为Nanoservices的SOA反模式,它讨论了这种平衡

要记住的另一件事是,Web服务API并不自动意味着这是一个服务边界。属于较大服务的多个API仍然可以连接到下面的同一个数据库。因此,例如,如果您的系统中的付款和订单属于一起,则不应将它们分开,因为它们是不同的API(在许多系统中,这些确实是不同的问题,但同样,这不是自动的)

当您确实发现服务逻辑分离时,您应该遵循Marco的建议,并确保服务是隔离的,不要共享数据库。以这种方式隔离服务有助于他们改变的能力。然后,您可以使用composite front end将它们集成到UI中。您应该注意,这适用于应用程序的操作方面,因为您只需要每个服务中的一些项目。对于报告,您需要类似aggregated reporting的内容,即将不可变数据副本导出到为报告优化的中央数据库(例如非规范化星型模式等)。

答案 1 :(得分:2)

哦,我的朋友,你只是让整个场景变得复杂,但这不是你的错,像MSFT,甲骨文和其他大型企业级软件供应商这样的公司喜欢大做一些更容易的事情,他们这样做是因为:垂直扩展服务意味着更多的许可证。

你可以采取不同的方法,暂时忘掉所有那些重要的词,EJB,JPA ......就像曾经说过的聪明人一样,把大问题分成小部分,这样你就不会遇到大问题理论上应该更容易处理的几个小问题。

因此,您的系统中有一些服务:人员,支付系统,订单,产品,ERP ......暂时可以认为这些边界在业务实体方面是正确的。想象一下,这些服务是您公司的不同物理部门,这意味着他们只关心属于他们的数据,没有别的。

然后您可以说Payments部门有自己的数据库,这同样适用于Orders,当然他们仍然需要像所有部门那样相互通信,并且可以通过系统生成的公共代理键轻松实现。这一切意味着每个服务使用内部密钥维护其所有内部实体的参照完整性,但如果我需要将记录提供给其他服务,您可以使用Guid密钥,例如:

enter image description here

付款服务需要订单ID和客户ID,但这些实体属于他们自己的服务,因此不是共享每条记录的私钥(主键),而是每条记录都有一个主键和一个代理服务将用于在它们之间共享的外部密钥。问题是,你应该致力于构建松散耦合服务,每个服务都有自己的“小”数据库。每个服务还应该有自己的API,不仅应该由前端使用,还应该由其他服务使用。您应该避免的另一件事是使用DTC或其他事务管理提供程序作为服务范围的事务保证程序,只需使用不同的体系结构方法就可以轻松归档。

无论如何,请阅读,如果你还没有关于DDD的话,它会给你一个关于如何构建企业级软件的不同概述,以及顺便说一句,远离它们。

<强>更新

你可以使用像事件SOA这样的东西,但是让我们在这里保持简单。注册客户来到您的网站下订单。负责此事的服务是订单。产品的外部ID列表将提交给Orders服务,然后该服务会注册订单,此时订单处于“等待付款”状态,此服务返回公共Guid订单ID。对于要完成的订单,客户需要为货物付款。付款详细信息将提交给付款服务,该服务会尝试处理付款,但为此它需要订单详细信息,因为前端发送的唯一内容是订单ID,为此,它使用来自的订单ID(Guid orderId)订单的API。付款完成后,Payments服务会调用Order的API PaymentWasCompletedForOrder(Guid orderID)的另一种方法。如果有什么事你没有得到,请告诉我。

相关问题