我们正在构建一个新的基于Web的工业应用程序,最近几天困扰我们的一个问题是有关此体系结构上不同“微服务”之间的集成。
我正在使用微服务,但我们并没有完全接受定义真正微服务的概念。一个(也是我认为最大的区别)取决于这样一个事实,即我们在不同的模块上使用了相同的共享数据库(我称之为“微服务”)。我们系统的某种逻辑视图可以绘制为:
╔══════════════╗
║ Client ║ ══╗
╚══════════════╝ ║ (2)
║
▼
╔══════════════╗ (1) ╔══════════════╗
║ Serv. Reg. ║ <==> ║ API Gatew. ║
╚══════════════╝ ╚══════════════╝
█ █ █████████████ (4)
█ █ ████
╔══════════════╗ ╔══════════════╗ ╔══════════════╗
║ Module A ║ ║ Module B ║ ║ Module C ║ <===== "Microservices"
╚══════════════╝ ╚══════════════╝ ╚══════════════╝
║║ (3) ║║ (3) ║║ (3)
║║ ║║ ║║
╔══════════════════════════════════════════════════╗
║ Database Server ║
╚══════════════════════════════════════════════════╝
我们已经弄清楚的一些事情:
我们(或我本人)的困境在于如何进行不同模块之间的通信。我已经阅读了很多不同的模式和反模式来执行此操作,并且几乎每个人都会通过RestTemplate或Feign或Ribbon这样的专门客户端来告知API集成。
由于某些原因,我倾向于不喜欢这种方法,主要是HTTP请求的同步和无状态性质。 HTTP的无状态本质是我最大的问题,因为不同模块的服务层可以具有一些强大的绑定。例如,在模块A上启动的操作可能会对模块B和C产生影响,并且需要从“事务”的角度协调所有内容。我真的不认为HTTP是控制此的最佳方法!
我内心的Java EE部分大喊使用某种服务集成,例如EJB或RMI或最终不使用HTTP的任何东西。对我来说,将某个服务从模块A内的模块B连接起来,并确保它们一起参与交易会更加“自然”。
需要强调的另一件事是,数据库上最终的不一致之类的范式对于我们的客户来说是不够的,因为它们正在处理某种严重的数据。因此,“我保证会尽力处理数据”在这里不太合适。
提问时间:
与“微服务”打交道时,这种“服务集成”真的是一件事情吗?还是“资源整合”胜过它?
例如,似乎Spring提供了Spring Integration来实现服务之间的消息传递,就像EJB这样的技术一样。这是整合这些服务的最佳方法吗?我想念什么吗?
PS:您可以将我的“微服务”称为“微石”,我们通常在这里使用它们的名字。 :)
答案 0 :(得分:2)
AFAIK,通常,微服务方法假定在同一数据库/架构级别上,这些服务之间没有共享数据。
这意味着微服务被实现为业务逻辑中某个领域概念的“专家”,该概念足够广泛/复杂,足以“应得”微服务。
否则,微服务架构的许多优势就会消失:
独立。好吧,我们可以按照自己的节奏部署新版本的微服务,甚至不共享技术堆栈,依此类推。现在,如果我更改了一个架构(即使是很小的变更),比如说添加或在更极端的情况下更改或删除列,那么其他微服务将如何知道这已经发生。我是否真的可以按自己的方式部署每个服务商,但现在必须一次部署所有服务商?可悲的是,第二种选择是唯一可行的选择。所以没有真正的独立性
可扩展性。的确,每个微服务都可以独立扩展,这听起来不错。但是现在,由于它们都共享同一个存储,因此将针对该存储执行所有操作,因此在规模上它将很快成为一个真正的瓶颈,因此没有应用真正的可伸缩性。
你知道它的去向...
现在,在转向微服务方法时,交易问题,或者从更一般的意义上讲,数据完整性确实是要解决的最大挑战之一。
通常(再次根据我的经验),人们会调整用例,使最终的一致性也足够好,然后就没有问题了。一种或另一种方式,应避免使用分布式事务之类的东西,因为它们会使代码变得极其复杂,并且是维护工作的噩梦。
因此,最重要的是,您应该首先考虑微服务方法是否适合您的应用程序;如果是,则如何以一种能够满足所有主要用例的方式真正分解数据。
答案 1 :(得分:2)
Microsevices方法。首先,您应该对应用程序对域寻址有深入的了解。并且应该具有识别应用程序模块的bounded context的能力。如果您已经确定了这种粒度模块,则可以轻松地将它们转换为微服务。每个有界上下文都应该高度独立,这意味着必须在微服务中处理单个事务。由于您使用的是通用数据库,因此我假设它是严格遵循ACID属性的RDBMS。如果您必须在与DB的事务中获得ACID属性,则要创建的每个微服务都必须独立处理事务管理。换句话说,如果您可以将事务概念化为事件的顺序,并且每个事件本身都可以自行维护其状态,那么您可以将微服务发展为引擎来处理这些事件。如果最终的设计中,微服务必须彼此依赖,并且在大多数用例中微服务本身无法处理状态/事件/事务,则您必须重新考虑您的方法。您试图实现的目标称为shared database pattern。有人认为它是anti-pattern。
答案 2 :(得分:0)
您可以研究域驱动设计来考虑服务的上下文。聚合应该是您进行交易的界限。
要考虑服务之间的通信,您可以尝试识别Events
并使用它们协调您在多个服务中的状态更改。
如果确实需要来自多个外部服务的大量数据来进行事务,则可以在需要数据的服务中保留外部数据的副本。 Projections
通常被调用,并且可以通过外部服务发布的事件来保持最新状态。
通常,在服务之间共享表是一种不好的做法,只有一个服务应为所有者。