In the last few posts on sagas, we looked at a variety of patterns of modeling long-running business transactions. However, the general problem of message routing doesn’t always require a central point of control, such as is provided with the saga facilities in NServiceBus. Process managers offer a great deal of flexibility in modeling complex business processes and splitting out concerns. They come at a cost though, with the shared state and single, centralized processor.

Back in our sandwich shop example, we had a picture of an interaction starting a process and moving down the line until completion:

Not quite clear in this picture is that if we were to model this process as a saga, we’d have a central point in which all messages must flow to for decisions to be made on the next step. But is there really any decision to be made in the picture above? In a true saga, we have a sequence of steps and a set of compensating actions (in a very simplistic case). Many times, however, there’s no need to worry about compensations in case of failures. Nor does the order in which we do things change much.

Humans have already found that assembly lines are great ways of breaking down a long process into individual steps, and performing those steps one at a time. Henry Ford’s Model T rolled off the assembly line every 3 minutes. If only one centralized worker coordinated all steps, it’s difficult to imagine how this level of throughput could be achieved.

The key differentiator is that there’s nothing really to coordinate – the process of steps is well-defined and known up front, and individual steps shouldn’t need to make decisions about what’s next. Nor is there a need for a central controller to figure out the next step – we already know the steps up front!

In our sandwich model, we need to tweak our picture to represent the reality of what’s going on. Once I place my order, the sequence of steps to fulfill my order are known up front, based on simply examining my order. The only decision to be made is to inspect the order and write the steps down. My order then flows through the system based on the pre-defined steps:

Each step doesn’t change the order, nor do they decide what the next step is (or even care who the next step is). Each step’s job is to simply perform its operation, and once completed, pass the order to the next step.

Not all orders have the same set of steps, but that’s OK. As long as the steps don’t deviate from the plan once started, we don’t need to have any more “smarts” in our steps.

It turns out this pattern is a well-known pattern in the messaging world (which, in turn, borrowed its ideas from the real world): the routing slip pattern.

Routing slips in NServiceBus

Routing slips don’t exist in NServiceBus, but it turns out it’s not too difficult to implement. A routing slip represents the list of steps (and the progress), as well as a place for us to stash any extra information needed further down the line:

We can attach our routing slip to the original message, so that each step can inspect the slip for the next step. We’ll kick off the process when we first send out the message:

Each handler handles the message, but doesn’t really need to do anything to pass it down the line, we can do this at the NServiceBus infrastructure level.

The nice aspect of this model is that it eliminates any centralized control. The message flows straight through the set of queues – leaving out any potential bottleneck our saga implementation would introduce. Additionally, we don’t need to resort to things like pub-sub – since this would still force our steps to be aware of the overall order, hard-coding who is next in the chain. If a customer doesn’t toast their sandwich – it doesn’t go through the oven, but we know this up front! No need to have each step to know both what to do and what the next step is.

I put the message routing implementation up on NuGet and GitHub, you just need to enable it on each endpoint via configuration:

If you need to process a message in a series of steps (known up front), and want to keep individual steps from knowing what’s next (or introduce a central controller), the routing slip pattern could be a good fit.

Saga alternatives – routing slips的更多相关文章

  1. How to implement long running flows, sagas, business processes or similar

    转自:https://blog.bernd-ruecker.com/how-to-implement-long-running-flows-sagas-business-processes-or-si ...

  2. 让你的saga更具有可伸缩性(Scaling NServiceBus Sagas)

    https://lostechies.com/jimmybogard/2013/03/26/scaling-nservicebus-sagas/ 当我们使用NServiceBus sagas (pro ...

  3. ASP.NET路由[ASP.NET Routing]

    ASP.NET路由[ASP.NET Routing] ASP.NET路由允许你在使用URL时不必匹配到网站中具体的文件,因为这个URL不必匹配到一个文件,你使用了描述用户行为且更容易被用户理解的URL ...

  4. 解读ASP.NET 5 & MVC6系列(12):基于Lamda表达式的强类型Routing实现

    前面的深入理解Routing章节,我们讲到了在MVC中,除了使用默认的ASP.NET 5的路由注册方式,还可以使用基于Attribute的特性(Route和HttpXXX系列方法)来定义.本章,我们将 ...

  5. 解读ASP.NET 5 & MVC6系列(11):Routing路由

    新版Routing功能介绍 在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和We ...

  6. scala - multiple overloaded alternatives of method bar define default arguments

    同名同位置默认参数不能overload def bar(i:Int,s:String="a"){} def bar(i:String,s:String="b") ...

  7. [ASP.NET MVC 小牛之路]07 - URL Routing

    我们知道在ASP.NET Web Forms中,一个URL请求往往对应一个aspx页面,一个aspx页面就是一个物理文件,它包含对请求的处理. 而在ASP.NET MVC中,一个URL请求是由对应的一 ...

  8. ASP.NET MVC Routing学习笔记(一)

    Routing在ASP.NET MVC中是非常核心的技术,属于ASP.NET MVC几大核心技术之一,在使用Routing之前,得先引入System.Web.Routing,但其实不用这么麻烦,因为在 ...

  9. Routing 功能概述 - 每天5分钟玩转 OpenStack(98)

    路由服务(Routing)提供跨 subnet 互联互通功能. 例如前面我们搭建了实验环境: cirros-vm1      172.16.100.3        vlan100 cirros-vm ...

随机推荐

  1. AngularJs学习——实现数据绑定的三种方式

    三种方式: 方式一:<h5>{{msg}}</h5>  此方式在页面刷新的时候会闪现{{}} 方式二:<h5 ng-bind="msg">< ...

  2. loj6030 「雅礼集训 2017 Day1」矩阵

    传送门:https://loj.ac/problem/6030 [题解] 以下把白称为0,黑称为1. 发现只有全空才是无解,否则考虑构造. 每一列,只要有0的格子都需要被赋值1次,所以设有x列有含有0 ...

  3. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  4. <script>中的async与defer属性

    1.script元素中的defer属性 1.1说明 使用该属性可以使脚本延迟到文档完全被解析和显示之后再按照原本的顺序执行,即告诉浏览器立即下载脚本,但延迟执行,该属性只对外部脚本有效 1.2使用方法 ...

  5. OpenWRT介绍

    1. 介绍 OpenWRT是一款第三方路由器固件, 其特别在于开放性, 如它的文件系统可写, 用户可在路由器上安装需要的第三方软件.通过刷入OpenWRT, 我们可以完成如下事情 - DLNA共享 - ...

  6. Google I/O完整盘点,这才是地球上最「性感」的发布会

    https://news.cnblogs.com/n/569588/ Google.ai:展现 AI 最好的一面 Google 今天新发布了第二代的 Tensor 处理单元(TPU),这是一个云计算硬 ...

  7. java对象内存大小评估

    Java对象的内存布局:对象头(Header).实例数据(Instance Data)和对齐填充(Padding).无论是32位还是64位的HotSpot,使用的都是8字节对齐.也就是说每个java对 ...

  8. 关于测试url传值的问题

    url1:http://localhost:8080/fms/finan/isRiskCustomer.action?customername="xxxxxxxx"; 如上这样写, ...

  9. python中的enumerate使用

    enumerate函数用于遍历序列中的元素以及它们的下标,多用于在for循环中得到计数,enumerate参数为可遍历的变量,如 字符串,列表等 一般情况下对一个列表或数组既要遍历索引又要遍历元素时, ...

  10. WebDriver框架之自动运行失败的case

    大家在运行自动化case的时候都会碰到失败的情况,有的时候可能是被测程序有bug,还有就是网络的问题,如果想采取失败的case再运行一次的机制,那么有bug的情况,即使再运行N次还是失败,那么如果是网 ...