如何将不同的“微服务”集成到交易中?

时间:2019-01-17 07:06:55

标签: spring spring-boot spring-integration microservices spring-cloud

我们正在构建一个新的基于Web的工业应用程序,最近几天困扰我们的一个问题是有关此体系结构上不同“微服务”之间的集成。

我正在使用微服务,但我们并没有完全接受定义真正微服务的概念。一个(也是我认为最大的区别)取决于这样一个事实,即我们在不同的模块上使用了相同的共享数据库(我称之为“微服务”)。我们系统的某种逻辑视图可以绘制为:

                  ╔══════════════╗
                  ║    Client    ║ ══╗
                  ╚══════════════╝   ║ (2)
                                     ║
                                     ▼        
        ╔══════════════╗  (1) ╔══════════════╗
        ║  Serv. Reg.  ║ <==> ║  API Gatew.  ║
        ╚══════════════╝      ╚══════════════╝
            █       █   █████████████     (4)
           █         █              ████
╔══════════════╗  ╔══════════════╗  ╔══════════════╗
║   Module A   ║  ║   Module B   ║  ║   Module C   ║  <===== "Microservices"
╚══════════════╝  ╚══════════════╝  ╚══════════════╝
        ║║ (3)           ║║ (3)            ║║ (3)
        ║║               ║║                ║║
╔══════════════════════════════════════════════════╗
║                Database Server                   ║
╚══════════════════════════════════════════════════╝

我们已经弄清楚的一些事情:

  • 客户端(外部系统,前端应用程序)将使用发现/路由模式访问不同的后端模块。我们正在考虑将Netflix OSS Eureka和Zuul结合使用。服务(模块A,B,C)在服务注册模块上进行自身注册(4),并通过注册向API网关坐标(1)进行注册,以找到可以满足请求的服务实例(2)。
  • 所有不同的模块都使用相同的数据库。 (3)这更多是客户的请求,而不是架构决定。

我们(或我本人)的困境在于如何进行不同模块之间的通信。我已经阅读了很多不同的模式和反模式来执行此操作,并且几乎每个人都会通过RestTemplate或Feign或Ribbon这样的专门客户端来告知API集成。

由于某些原因,我倾向于不喜欢这种方法,主要是HTTP请求的同步和无状态性质。 HTTP的无状态本质是我最大的问题,因为不同模块的服务层可以具有一些强大的绑定。例如,在模块A上启动的操作可能会对模块B和C产生影响,并且需要从“事务”的角度协调所有内容。我真的不认为HTTP是控制此的最佳方法!

我内心的Java EE部分大喊使用某种服务集成,例如EJB或RMI或最终不使用HTTP的任何东西。对我来说,将某个服务从模块A内的模块B连接起来,并确保它们一起参与交易会更加“自然”。

需要强调的另一件事是,数据库上最终的不一致之类的范式对于我们的客户来说是不够的,因为它们正在处理某种严重的数据。因此,“我保证会尽力处理数据”在这里不太合适。

提问时间:

与“微服务”打交道时,这种“服务集成”真的是一件事情吗?还是“资源整合”胜过它?

例如,似乎Spring提供了Spring Integration来实现服务之间的消息传递,就像EJB这样的技术一样。这是整合这些服务的最佳方法吗?我想念什么吗?

PS:您可以将我的“微服务”称为“微石”,我们通常在这里使用它们的名字。 :)

3 个答案:

答案 0 :(得分:2)

AFAIK,通常,微服务方法假定在同一数据库/架构级别上,这些服务之间没有共享数据。

这意味着微服务被实现为业务逻辑中某个领域概念的“专家”,该概念足够广泛/复杂,足以“应得”微服务。

否则,微服务架构的许多优势就会消失:

  1. 独立。好吧,我们可以按照自己的节奏部署新版本的微服务,甚至不共享技术堆栈,依此类推。现在,如果我更改了一个架构(即使是很小的变更),比如说添加或在更极端的情况下更改或删除列,那么其他微服务将如何知道这已经发生。我是否真的可以按自己的方式部署每个服务商,但现在必须一次部署所有服务商?可悲的是,第二种选择是唯一可行的选择。所以没有真正的独立性

  2. 可扩展性。的确,每个微服务都可以独立扩展,这听起来不错。但是现在,由于它们都共享同一个存储,因此将针对该存储执行所有操作,因此在规模上它将很快成为一个真正的瓶颈,因此没有应用真正的可伸缩性。

你知道它的去向...

现在,在转向微服务方法时,交易问题,或者从更一般的意义上讲,数据完整性确实是要解决的最大挑战之一。

通常(再次根据我的经验),人们会调整用例,使最终的一致性也足够好,然后就没有问题了。一种或另一种方式,应避免使用分布式事务之类的东西,因为它们会使代码变得极其复杂,并且是维护工作的噩梦。

因此,最重要的是,您应该首先考虑微服务方法是否适合您的应用程序;如果是,则如何以一种能够满足所有主要用例的方式真正分解数据。

答案 1 :(得分:2)

在进行域驱动设计时,会出现

Microsevices方法。首先,您应该对应用程序对域寻址有深入的了解。并且应该具有识别应用程序模块的bounded context的能力。如果您已经确定了这种粒度模块,则可以轻松地将它们转换为微服务。每个有界上下文都应该高度独立,这意味着必须在微服务中处理单个事务。由于您使用的是通用数据库,因此我假设它是严格遵循ACID属性的RDBMS。如果您必须在与DB的事务中获得ACID属性,则要创建的每个微服务都必须独立处理事务管理。换句话说,如果您可以将事务概念化为事件的顺序,并且每个事件本身都可以自行维护其状态,那么您可以将微服务发展为引擎来处理这些事件。如果最终的设计中,微服务必须彼此依赖,并且在大多数用例中微服务本身无法处理状态/事件/事务,则您必须重新考虑您的方法。您试图实现的目标称为shared database pattern。有人认为它是anti-pattern

答案 2 :(得分:0)

您可以研究域驱动设计来考虑服务的上下文。聚合应该是您进行交易的界限。

要考虑服务之间的通信,您可以尝试识别Events并使用它们协调您在多个服务中的状态更改。 如果确实需要来自多个外部服务的大量数据来进行事务,则可以在需要数据的服务中保留外部数据的副本。 Projections通常被调用,并且可以通过外部服务发布的事件来保持最新状态。

通常,在服务之间共享表是一种不好的做法,只有一个服务应为所有者。