无服务器领域的微服务编排与编舞 - theburningmonk.com


编排Orchestration和编舞Choreography是微服务架构中的两种交互方式。
在编排Orchestration中,有一个控制器(“编排器”)控制服务之间的交互。它决定了业务逻辑的控制流,并负责确保一切按提示进行。这遵循了请求-响应范例。
在编舞Choreography中,每个服务都是独立工作的。它们之间没有硬依赖性,它们仅通过共享事件松散耦合。每个服务都侦听它感兴趣的事件并做自己的事情。这遵循事件驱动的范例。
与往常一样,两者都不一定比对方好。根据上下文,一个可能比另一个更合适。而且由于Lambda本身是固有的事件驱动型,因此编舞Choreography已在无服务器社区中变得非常流行。我非常支持这种方法,并使用EventBridge,SNS和Kinesis等服务构建了许多事件驱动的系统。
但是,在这篇文章中,我想谈谈什么时候不是一个好主意,什么时候应该考虑使用编排Orchestration方法。
在实现工作流时,您应该更喜欢在微服务的有界上下文中进行编排Orchestration,而更喜欢有界上下文之间的编舞Choreography。
 
编舞Choreography
想象一下,您正在建立一种食品订购服务,客户可以从他们最喜欢的餐馆订购外卖食品。典型的订单流程可能涉及以下五个步骤。

我们可以将这五个步骤建模为事件:

  • order_placed
  • restaurant_notified
  • order_accepted
  • user_notified
  • order_completed

通过这些事件,我们可以使用事件驱动的方法来实现订单流。

  1. 客户下订单。
  2. place-order函数发布order_placed事件。
  3. notify-restaurant函数由order_placed事件触发。
  4. notify-restaurant 函数通过SNS向餐厅发送消息。
  5. notify-restaurant函数发布restaurant_notified事件。
  6. 餐馆在其移动应用中收到新的订单通知。
  7. 餐厅单击Accept Order应用程序,该应用程序将调用ordersAPI。
  8. accept-order函数发布order_accepted事件。
  9. notify-user函数由order_accepted事件触发。
  10. notify-user 函数将订单确认电子邮件发送给客户。
  11. notify-user函数发布user_notified事件。
  12. 顾客看到订单确认并急切地等待食物到达。
  13. 餐厅将食物交付给顾客。
  14. 餐厅点击Complete Order应用中的,以确认已下达订单。这将调用ordersAPI。
  15. complete-order函数发布order_completed事件。

每个函数完全独立地发挥作用。他们都没有整体订单流程的概念,他们每个人都只关心:
  • 他们感兴趣的事件是什么。
  • 他们应该做什么。
  • 完成任务时应发布哪些事件。

优点
  • 流程的每个步骤都可以独立更改。
  • 流程的每个步骤都可以独立缩放。
  • 没有单点故障。
  • 其他系统可以基于这些事件-例如,promo-code服务可能对该order_completed事件感兴趣,并向客户发送折扣券。
  • 这些事件本身就是有用的人工制品,可以馈入数据湖以生成商业智能报告。

缺点
  • 端到端的监视和报告很困难。
  • 难以实现超时。
  • 订单流未明确建模,仅作为系统功能的紧急属性而存在。这样,它只能被理解为能够端到端理解系统的人的心智模型。

从业务的角度来看,这也引出了一个问题:“这些流程真的分开吗?还是它们在一个流程中不同的步骤?”。
对于像这样的关键业务工作流程,您是否不希望某人或某个团队对此负责并承担责任?当出现问题并且您每小时损失数百万美元时,您是否要一个人满为患的房间,因为没人能理解端到端的流程?
而且,如果公司中很少有人了解这种关键流程的工作原理,那么如果这些人曾经离开公司,就会给企业带来生存风险。

 
编排Orchestration
为了实现编排方法,我可能会使用诸如Step Functions之类的东西,并将订单流建模为状态机。

还值得记住的是,尽管我们不再需要使用事件来触发订单流程的下一步,但这些事件本身仍然是有用的人工制品。因此,我们应该Task在状态机中发布状态相同的事件。例如,在Notify User状态通过SES通知用户之后,Task还要发布user_notified事件。
这意味着我们仍然可以将订单流与希望在与订单相关的事件之上构建功能的其他业务部门分离。前面提到的promo-code服务仍然可以order_completed像以前一样依赖该事件。

优点

  • 端到端的监视和报告很简单,因为“步进功能”为您提供了内置的可视化和审计历史记录。
  • 易于实现的超时-例如,餐厅接受订单或整个订单持续时间。
  • 业务逻辑合而为一,并且易于维护和管理。
  • 对订单流进行建模并控制其来源。您可以在“步骤功能”控制台中从字面上看到它。
  • 对订单流进行建模并控制其来源。是的,将其视为两名职业球员是如此重要!

缺点
  • 必须学习另一项AWS服务。
  • 在25 $每百万状态转换(其计算Start和End方式),步功能是一个昂贵的服务。
  • 如果“步进功能”关闭,则无法处理任何订单。尽管对于Lambda,EventBridge或对该订单流的工作至关重要的任何服务都可以这么说。

 
混合方式
在有限的范围内,我有一组特定的职责与业务领域保持一致。希望有少量组件可以同时装在我的脑海中。由于他们都共同努力以实现某些特定的业务能力,例如处理付款,因此它们形成了一个高度凝聚力的部门。而且由于我拥有该微服务的有界上下文中的所有内容,因此只要不中断与外部服务的合同,我就可以自由地进行更改和重组。
我经常看到通过SQS / SNS / EventBridge中的消息对有限上下文中的工作流进行了编舞。
一般来说,我认为这是一个坏主意。


在实现业务工作流时,请允许我遵循我的经验法则:在微服务的有界上下文中使用编排,但在有界上下文之间使用编舞。