业务流程的新实现:微服务和事件编排

本文介绍如何在微服务架构通过事件编排实现业务流程的无限灵活实现,克服了以往SOA中ESB总线的中央治理的局限。

关键词:
1.在微服务架构中,遇到长时间运行并跨越多个微服务边界调用的流程并不少见。

2.具有相应编排功能的、基于事件的架构是一种越来越常见的方式,可以减少耦合。

3.这个想法的核心是:所有的微服务器可以订阅与其业务相关的其他服务发生的事件。这可以使用异步消息传递或者作为REST服务来完成。

4.该文章作者探索了他们称之为“事件命令转换(banq注:Saga模式)”的模式,避免了传统SOA的中央控制器。

5. 为了实现业务流程功能,您可以利用现有的轻量级状态机和工作流引擎。将这些引擎嵌入到您的微服务中,避免传统SOA的中央工具或中央治理。

原文大意:

假设我们想设计一个微服务架构来实现一些相当复杂的“端到端”用例,比如基于网络零售商的订单履行流程。显然,这将涉及多个微服务的调用。因此,我们必须处理跨越单个微服务边界的业务流程。但这种跨服务流会遭遇一些挑战。在本文中,我们将介绍“事件命令转换”这个有用的模式,介绍如何解决实现跨越微服务流程的复杂性,同时不要引入任何中央控制器。

首先,我们必须提出一个初步的微服务环境,并定义微服务的范围及其范围。我们的目标是最大程度地减少各种服务之间的耦合,并使其独立部署。通过这样做,我们希望最大化团队的自主权; 对于每个微服务,应该有一个专门职能的团队照顾它。由于这对我们尤为重要,因此我们决定采用更粗略的方法,并设计一些围绕业务功能构建的独立服务。这就产生了以下微服务:

1.付款服务 - 团队负责处理与“钱”有关的一切事宜
2.库存服务 - 团队负责照料库存物品
3.装运服务 - 团队负责“向客户移动东西”

网络商店本身可能会包含更多的微服务,例如搜索,目录等。当我们专注于订单履行时,我们只对一个网上商店相关服务感兴趣,允许客户下订单。


长时间流程

我们必须考虑整体顺序执行的一个重要特征:这是一个长期运行的流程。关于“长期运行”一词,我们的意思是说,直到订单处理完成后,可能需要几分钟,几个小时甚至几周的时间。

请考虑以下示例:每当信用卡在付款期间被拒绝时,客户有一周时间提供新的付款明细。这意味着订单可能需要等待一个星期。本文将针对这种长期运行的实现方法进行更详细地讨论。

事件协作

我们不讨论这篇文章中的沟通模式的利弊,而是决定在服务之间引入以事件为中心的沟通模式来解决我们的问题。

事件协作理念的核心是:所有的微服务器都会在事件相关的事件发生时发布事件。其他服务可以订阅该事件并进行某些操作,通过事件协作,服务之间的高度解耦成为默认设计。此外,实现我们在微服务架构中寻找的那种分散数据管理变得容易和自然。

这一概念在“ 领域驱动设计”(Domain Driven Design)中得到了很好的理解,该系统目前正在加速微服务流程和一般互动分布式系统的“新常态”。

请注意,事件协作可以通过异步消息传递实现,但也可以通过其他方式实现。微服务可以发布其事件的REST流。

事件命令转换

我们的订单履行是从订单下达事件开始,然后是客户付款。支付服务成功完成了收款,然后我们将货物托运,并送达客户。

事件的定义:通知您有关发生的相关事实以及某些其他服务可能感兴趣。

在我们的示例中,支付服务监听结帐服务中的“订单下达Order Placed ”事件。事件命令转换模式是确保负责做出业务决策的组件(现在需要付款)将事件(Order Placed)转换为命令(Retrieve Payment实现支付)。该命令可以发送到接收事件的支付服务。


编排与编排 - 业务流程的权力治理

端到端的流程逻辑是分散管理,职责是分散的,避免上帝式的服务中央控制就需要认真对待团队的职责和自主权的问题。对订单实现端到端的职责分散意味着“付款”就是一个黑盒子。您只负责要求执行其工作(检索付款)并等待其完成:收到付款即可,不需要关心其具体怎么做。

比如前面提到的业务需求,只要信用卡被拒绝,客户就有一周时间提供新的付款明细。我们也就可能在订单服务中实现这样的逻辑,但只有当付款服务提供的命令是非常细粒度的才有这种可能。如果支付小组认真对待自己的业务能力和相关职责,那么这样做可能需要一段时间,它需要确定收取付款的职责(banq注:说白了,需要更多人机交互说明这个环节很重要,工作人员需要反复确认核实,这些都是认真负责的意思,端到端流程这种分散方式便于人工介入)。

在高度分散的组织中,端到端订单服务将尽可能精简,因为其端到端流程的大多数方面将由专门从事自身业务能力的其他服务机构自主管理。付款服务是这个原则的一个例子:付款团队有责任实施收取付款所需的一切。

在谈论业务流程的实施时,这是一个重要的考虑因素和一个常见的误解:并不一定意味着您需要将整个流程设计成一个整体,让一个中央协调者执行它,就像传统的SOA和BPM一样。

如果认为分拆传统的集中流程设计到端到端的流程逻辑会增加系统的复杂性,那么您可能是正确的。而且需要首先引入微服务架构:单体架构通常更容易,但是当系统发展并且不能再由单个团队处理时,它们将达到极限。

总结我们迄今为止所讨论的内容:编舞是微观服务架构的基本模式。我们建议遵循这种模式作为一个重要的经验法则。但是,当涉及业务流程时,不要创建纯粹的事件链,而是实现分散的流程逻辑,并改用事件命令转换模式。负责决定行动的微服务也应负责将事件转换为命令。

流程逻辑实现

我们来看看长时间运行的流程逻辑的实现。长时间运行的流程需要保存状态,简单的方法是将订单状态存储为某些实体的一部分,例如代码片段1所示。


public class OrderStatus {
boolean paymentReceived = false;
boolean goodsFetched = false;
boolean goodsShipped = false;
}

或者你可能会使用你最喜欢的Actor演员框架。我们在这里讨论基本选项。所有这些都在一定程度上起作用,但是一旦开始实施长时间运行所需的状态,通常您会面临额外的需求:您如何实现等待七天?如何处理错误和重试?你如何评估订单的周期时间?在哪种情况下,由于缺少付款而取消订单?如果我在处理线上某处有一些订单,我该如何更改流程?

这可能导致大量编码,最终导致闭关造车的框架。在受影响的项目上工作的团队也投入了大量的努力。所以我们可以看看一个不同的方法:利用现有的框架。在本文中,我们使用Camunda开源引擎来说明具体的代码示例。我们来看看Code Snippet 2。


engine.getRepositoryService().createDeployment()
.addModelInstance(Bpmn.createExecutableProcess("order")
.startEvent()
.serviceTask().name(
"Retrieve payment").camundaClass(RetrievePaymentAdapter.class)
.serviceTask().name(
"Fetch goods").camundaClass(FetchGoodsAdapter.class)
.serviceTask().name(
"Ship goods").camundaClass(ShipGoodsAdapter.class)
.endEvent().camundaExecutionListenerClass(
"end", GoodsShippedAdapter.class)
.done()
).deploy();

引擎现在运行这个流程的实例,跟踪他们的状态,并以持续的方式来缓解灾难或长时间的等待。适配器逻辑如代码片段3所示:


public class RetrievePaymentAdapter implements JavaDelegate {
public void execute(ExecutionContext ctx) throws Exception {
// Prepare payload for the outgoing command
publishCommand(
"RetrievePayment", payload);
addEventSubscription(
"PaymentReceived", ctx);
}
}


(banq注:省去介绍Camunda作为工作流引擎和可视化开发方式两个部分)

处理复杂流程要求

众所周知,魔鬼在细节上。微服务只能实现“ 最终一致性 ”(柔性事务机制,不同于JTA的2PC刚性事务机制),抓住一些报错并触发补偿机制。Camunda引擎的补偿机制知道过去成功执行哪些活动,并自动执行定义的补偿活动,这很好地实现了所谓的Saga模式。

请注意,逻辑仍然存在于(可能非常精简)的微服务(订单服务)中,而总体流程的其他部分将由负责这些部件的团队维护。不需要任何中央控制器 - 流程逻辑是分布式的。

为什么传统BPM产品不是微服务的菜?

提供长时间运行服务所需的流程逻辑功能的现有工具通常被称为工作流或BPM引擎。然而,在“旧的SOA”中,业务流程管理(BPM)会出现错误,特别是在开发人员中,这种错误导致声誉不佳。他们认为,他们获得了一个僵化的,整体的,不利于开发者的且昂贵的工具,迫使他们遵循一些模型驱动的、专有的、所谓零代码的方法。一些BPM供应商真的提供了在微服务领域无法使用的平台。

克服误解的一个重要方面是认真考虑词语含义。我们在这里提供的流程不一定是“业务流程”,这些流程也可能是涉及人机交互的“工作流程”。(传统的BPM产品不适合人机交互频繁的流程)

本文的订单履行示例。您可以在GitHub上找到源代码。

微服务和事件驱动架构能很自然地配合在一起。事件编排能够实现分散数据管理,最大限度减少耦合。

原文:Know the Flow! Microservices and Event Choreographies

banq总结: 传统SOA是基于单体整体系统抽象出流程,但是这种流程编排不利于深度灵活的流程定制,而基于微服务的端到端订阅方式,只要关注前置事件发生即可(类似二叉树只要实现父子关系就可以一样),如果改变关注对象,当前微服务也可以迅速重启进而改变流程。