Saga的实现模式——观察者(Saga implementation patterns – Observer)

https://lostechies.com/jimmybogard/2013/03/11/saga-implementation-patterns-observer/

侵删。

NServiceBus sagas 是一个Process Manager pattern的实现,在实现的时候经常使用它的一两种主要形式。虽然各有差别,但总的来说saga的实现也就总是那几种。

第一种是观察者模式。作为一个观察者,saga通过响应事件来协调业务:

image

 

观察者有一些特性:

  • 消息以事件的形式接收
  • saga并不控制消息接收的顺序

因为saga不控制消息的顺序并且这些消息都是事件,所以saga是一个观察者。它自身不影响外部服务,但是它观测每个服务发布的服务。

观察者其他的一个有趣的特性是:它的职责是在它接受到所有事件之后它要协调整个业务,类似于这样:

image

 

这个和Scatter/Gather pattern有些相似。saga需要保证自身能够追踪收到的消息。除了接收消息,它还会记录已经收到的消息和检查是否需要进行到下一步的所有相关消息都已经收到。

这个一个简单的工作流模式, 但要注意的是它不知道什么消息会以什么顺序收到。

为了看这个模式如何运作,我们可以参考一个真实世界的场景来看看这种模式的工作方式。

快餐店的消息流转——麦当劳

学习分布式系统的一个有趣的事情就是它的应用例子实际上就在我们生活之中。一个在真实世界中的很好的saga观察者模式的例子就是麦当劳的订单处理过程。

客户订单中食物的准备工作不是按照一个固定的顺序来的。麦当劳有很多的工作台,这些工作台是相对独立的。在一个订单中,我们可能需要以下的食物:

  • 三明治
  • 饮料
  • 色拉
  • 薯条
  • 咖啡

呃,当然还有其他的东西。每一个工作台都有他们自己的工人,每个工人都有他们自己的工作队列。一个典型的订单处理过程看起来应该是这样的:

 

image

整个流程从客户下一个订单(1)开始。如果这个订单被接受(麦当劳收到钱了),一个事件就被广播到所有与订单相关的食品准备工作台(2)。每个工作台上面都有一个屏幕,就像一个待完成的工作队列。

只有与这个工作台相关的订单信息展示在屏幕上面。如果订单里面没有薯条,那么制造薯条的工作台就不会有任何关于这个订单的信息。

每个工作台的工作都和其他工作台的工作相独立。制造薯条的工作台就不需要制造饮料工作台的信息来完成工作。

当每个工作台都完成各自的工作之后,他们把食物送到柜台(3)——在那里,每个订单都被分别装在各自的托盘里面。每一个成食物制作的员工都要弄清楚他做好的食物应该放在哪个托盘里面——可以根据订单号来判断。在每个工作台的屏幕上,订单都会根据订单号分开,这样每个工作台都能区分每个订单。

每当一个工作台把准备好的食物放到托盘的时候,员工就会检查托盘上的所有食物有没有完全准备好。这个动作会在每一个食物放到托盘上面的时候完成,我们必须重复地检查是否订单上的食物已经准备好。并没有人专门负责这个检查工作——每个完成食物制作的员工应该完成这种检查。

一旦一个员工确定订单上的食物都准备好了,他们就会呼叫订单号然后客户就会过来把托盘拿走(4)。

在用NServiceBus实现saga之前,我们已经在现实世界中观察saga是怎么运行的了(虽然我们从来不这样称呼快餐店的这种模式叫saga)。

优点和缺点

和其他模式一样,这种模式也有一些优点和缺点。麦当劳使用这种模式就是为了最大化它处理订单的效率,但是并不是所有的快餐服务都使用这种模式。他的优点在于:

  • 每一个员工都和其他员工并行工作,提高他们总体的效率
  • 每个员工都和其他员工独立,并且和其他步骤无耦合
  • 我们可以很容易地添加额外的流程或者员工(麦当劳餐厅可以添加咖啡这种服务,但是不改变他们的总体订单处理模式)

然而这个模式也有一些缺点:

  • 引入了资源的争夺问题。我们不能让两个员工在同时往同一个托盘里面放食物——因为没有足够的空间。托盘/saga变成整个系统的阻塞点(choke point )——并且我们很难扩展这个空间。
  • 每一个步骤都要检查看看saga是否完成。这个就引入了额外的业务逻辑去检查什么事件已经完成和整个saga是否已经完成。

下次你去快餐店用餐的时候,看看他们是否是按照这种方式工作的。在一个每个订单生成步骤都独立的快餐店,他们都认为这种处理订单的方式是最有效率的:)

posted @ 2016-09-18 15:22  balavatasky  阅读(712)  评论(0编辑  收藏  举报