在c#中使用saga来控制任务队列工作流

本文关键字:控制 任务队列 工作流 saga | 更新日期: 2023-09-27 18:19:03

我希望建立一个分布式任务系统,其中代理将根据一定的工作流执行任务

saga的概念似乎非常适合这个用例,在这个用例中有两种模式:

1)控制器传奇:专用机器发送命令,等待回复,然后按顺序发送下一个命令,等等…

2)路由slip saga:步骤提前记录在消息本身中。

我想听听你对这些问题的看法:1)传奇故事真的适合这个用例吗?2)对于这个用例,它们中的哪一个是首选的?3)如果只有一些机器能够执行某些任务:我如何确保其他代理都不会接收到消息?(例如:任务可能是"执行此存储过程",我希望它只在专用于数据库的代理上运行)

EDIT(2015-10-24):(更多关于工作流程的信息)

我寻找的工作流程是这样的:一个10小时的工作分成10个块(小任务)。依赖关系图允许其中一些同时发生,而另一些则必须在下一个排队之前完成。我计划将这个工作流逻辑(依赖关系)合并到运行控制器(=saga)的机器中。如果我能轻松地改变工作流程,那将是最理想的(例如:在"步骤7"answers"步骤8"之间插入另一个任务(这两个都是小任务)。每个代理将同时运行几个任务(确切的数量最好由cpu/IO利用率决定)(即可能运行工作流#1的步骤3和工作流#2的步骤5)

谢谢

在c#中使用saga来控制任务队列工作流

1)传奇故事确实适合这个用例吗?

完美可能有点过分,但这是处理许多工作流的好方法。

2)对于这个用例,它们中的哪一个是首选的?

您更新的工作流表明,Saga将是工作流的一个很好的选择。添加步骤将需要代码更改和部署,但是用许多步骤处理长时间运行的工作流似乎是完美的。此外,在下一步之前协调多个异步步骤的完成是我使用传奇的常见用例。

3)如果只有一些机器能够执行某些任务:我如何确保其他代理都不会接收到消息?

的类型。每个活动都有一个与动作相对应的特定消息类型。如。"GetReportData"(执行存储过程?)对于该消息类型,您将拥有一组具有消费者的服务。只有它们将接收以该类型发布的消息。如果它比这更复杂,例如GetReportData,但只针对客户A的机器,而不是客户B的机器,那么你就进入基于内容的路由。这通常不被重视,如果可能的话,您可能希望找到另一种方法来为您的工作建模。在MassTransit中不支持基于内容的路由。

业务流程

saga适用于编排,特别是长时间运行的编排。我个人曾在一个设置中工作过,我们必须转换各种媒体,如图像,视频文件,还有powerpoint, pdf,字幕等,NServiceBus Sagas被使用在它以前使用的地方,它是建立在一个导致拥塞问题的投票数据库表上。

控制器与路由滑移

控制器和路由卡瓦都可以使用。您提到您想要轻松更改工作流,但没有提到您是否想要轻松更改已经实例化的工作流。控制器类型更容易"更新",路由卡在工作流中非常好,不能改变。

路由条携带它们的流,所以工作流可以很容易地从根本上改变而不影响现有的实例。它很难改变现有的实例,控制器是相反的,流可以修改,但需要向后兼容。

也有其他的变化,看看这篇文章由Jimmy Bogard:https://lostechies.com/jimmybogard/2013/05/14/saga-patterns-wrap-up/

<标题>不断变化的工作流程的h1> 常,创建saga实例的事件会完成其余步骤的设置。这成为了saga状态的一部分。如果工作流被更改,那么这不会影响现有的saga实例,除非您显式地希望这样做,或者使用If语句对步骤进行硬编码。

我对媒体转换传奇的经验是,工作流获取要执行的任务,将它们保持在传奇状态,并迭代这些步骤。

<标题> 消息模式

任务应该是一个应该建模为异步请求/响应的命令。根据响应执行下一步。Pubsub并不能很好地工作,因为多个'worker '会收到相同的'event'。

<标题> 任务

为每个任务创建一条消息。创建一个知道如何处理此消息的使用者。

例如:

服务X知道如何处理A、B和C服务Y知道如何处理D和E

<标题> 扩展

如果Service X需要额外的资源,那么你可以使用分布模式(MSMQ)或使用竞争消费者(RabbitMQ, Azure Storage Queues等)进行扩展。

基于内容的路由

避免使用

这样的结构
  • 服务X可以处理A、B、C,但实例1支持A、B,实例2支持C。
    • 可能最好把它分成三个服务。
  • 服务X和Y都知道如何处理D
    • 您如何决定将哪个服务发送给命令/请求?

如上所述,MassTransit不支持CBR, NServiceBus也不支持CBR,因为CBR经常被误用。

查看Udi Dahan的文章:

http://udidahan.com/2011/03/20/careful-with-content-based-routing/

我不确定我是否完全理解你的问题,但是…

我宁愿让代理来完成任务。因此,每个代理从适合"他"的任务列表中取出一个任务。任务应该按类型标记,以便正确的代理可以拾取它。每当代理准备好一个任务时,它就可以抓取另一个任务。当代理抓取一个任务时,它将被标记为忙。(可以保留时间戳来检测超时)