《无服务器之地》中的编排与编排

2020-11-16 14:08:38

在编排中,有一个控制器(“编制者”)控制服务之间的交互。它规定了业务逻辑的控制流,并负责确保一切按提示进行。这遵循请求-响应范例。

在编排中,每个服务都独立工作。它们之间没有硬依赖,它们只通过共享事件松散耦合。每个服务监听它感兴趣的事件,并做自己的事情。这遵循事件驱动的范例。

一如既往,两者都不一定比另一个更好。根据上下文的不同,其中一个可能比另一个更合适。由于Lambda本身本质上是事件驱动的,编排方法在无服务器社区中变得非常流行。我是这种方法的铁杆粉丝,已经使用EventBridge、SNS和Kinesis等服务构建了许多事件驱动系统。

然而,在这篇文章中,我想谈谈什么时候这不是一个好主意,什么时候你应该考虑使用编排方法。

TL;DR的意思是,在实现工作流时,您应该更喜欢在微服务的有界上下文中进行编排,但更喜欢在有界上下文之间进行编排。

想象一下,你正在建立一个订餐服务,顾客可以从他们最喜欢的餐厅点外卖。典型的订单流可能涉及以下五个步骤。

顾客看到订单确认后,急切地等待着食物的到来。

餐厅点击应用程序中的完整订单,确认订单已经送达。这将调用Orders API。

每项功能都是完全独立发挥作用的。他们中没有人有总体订单流的概念,他们各自只关心:

其他系统可以基于这些事件-例如,促销代码服务可能对ORDER_COMPLETED事件感兴趣,并向客户发送折扣券。

这些事件本身就是有用的人工制品,可以输入到数据湖中以生成商业智能报告。

订单流没有显式建模,只是作为系统所做工作的紧急属性而存在。因此,它只会被端到端理解系统的人的心理模型所捕获。

从业务的角度来看,这也回避了一个问题:“这些流程真的是分开的吗?抑或是同一过程中的不同步骤?“。

对于这样的业务关键型工作流,您难道不想让某个人或某个团队来负责它吗?当事情出了问题,你每小时损失数百万美元,你想让一屋子的人互相看着,因为没有人理解这个过程吗?

如果公司里几乎没有人了解这种关键流程是如何运作的,那么如果这些人离开公司,就会给公司带来生死存亡的风险。

为了实现编排方法,我可能会使用类似于步骤函数的方法,并将订单流建模为状态机。

同样值得记住的是,尽管我们不再需要使用事件来触发订单流的下一步,但这些事件本身仍然是有用的构件。因此,我们应该在状态机中发布来自任务状态的相同事件。例如,在NOTIFY USER状态通过SES通知用户之后,任务还应该发布USER_NOTIFIED事件。

这意味着我们仍然可以将订单流与其他业务部门分离,这些业务部门希望在与订单相关的事件之上构建功能。上述促销代码服务仍然可以像以前一样依赖于ORDER_COMPLETED事件。

端到端的监控和报告非常简单,因为STEP函数为您提供了内置的可视化和审核历史记录。

易于实现超时-例如,餐厅接受订单,或订单的整个持续时间。

业务逻辑集中在一个地方,易于维护和管理。

对订单流进行建模,并对其进行源代码控制。您可以在STEP Functions控制台中直接看到它。

对订单流进行建模,并对其进行源代码控制。是的,这很重要,应该算作两个专业选手!

每百万次状态转换收费25美元(顺便说一句,这包括开始和结束),Step Functions是一项昂贵的服务。

如果步骤功能关闭,则无法处理任何订单。尽管对于Lambda、EventBridge或对此订单流的工作至关重要的任何服务也可能会说同样的话。

在有限的上下文中,我有一组特定的职责,这些职责与某个业务领域保持一致。希望有一小部分组件可以同时放入我的大脑中。由于它们都在一起工作以实现某些特定的业务能力,如处理支付,因此它们形成了一个高度凝聚力的单元。而且,由于我拥有这个微服务的受限上下文中的所有内容,所以只要我不破坏与外部服务的合同,我就可以自由地更改和重组。

我喜欢使用事件以松散耦合的方式将不同的服务集成在一起。但我认为,如果它是在相同的受限上下文中完成的,那就不是一个好主意,因为工作流不是作为一个独立的概念而存在的,它明确地被捕获并受源代码控制。

在这些精心设计的工作流中,工作流仅作为松散连接的功能的总和而存在。正如我们在上面的外卖示例中所讨论的,这使得它们很难推理和调试。即使是工作流程级别的超时,甚至是任务级别的任务,也没有简单的方法来实现(例如,如果餐厅在10分钟内没有接受或拒绝订单,就会超时)。

如果这就是您现在所拥有的,那么您应该考虑将这些工作流转移到STEP函数。

但是,在受约束的上下文之间,我将通过SNS/EventBridge/Kinesis等发布和订阅事件。这是为了使更大系统的不同部分可以保持松散耦合,并且只在彼此的事件基础上构建,并且可以独立地发展和失败。

编排和编排不一定是相互排斥的。每当我在状态机中引入状态更改(例如将订单的状态从待定更改为已处理)时,我都会将这些状态更改作为事件发布。其他服务可以监听和响应这些状态更改,并将编排带入画面中。

当涉及到实现业务工作流时,让我给您留下我的经验法则:在微服务的有界上下文中使用编排,但在有界上下文之间使用编排。