NServiceBus 批处理一个长 运行 作业

NServiceBus batching a long running job

我正在做一个使用 NSB 的项目,真的很喜欢它,但这是我的第一个 NSB 解决方案,所以有点菜鸟。我们有一个工作需要每天运行处理会员——预计时间不会很长,因为工作简单,但可能会影响成千上万的会员,未来可能会影响数万或数十万.

让这一切都在一个处理程序中一次性发生感觉不对,但是让一个处理程序发现受影响的成员然后为每个成员触发单独的事件听起来有点相反。我可以想到其他一些方法,但想知道在 NSB 中是否有一种惯用的方法来处理这个问题?

编辑澄清:我正在使用 Schedule 在凌晨 3 点发送命令,该命令的处理程序将查询 SQL 数据库以获取需要处理的成员列表。处理将涉及每个成员 updating/inserting 一两行。我的问题是关于如何处理 NSB 中可能存在的大量成员列表。

编辑第 2 部分:工作现在需要 运行 每月,而不是每天。

您提到了一个 运行ning 过程,这听起来像是 Saga 的工作(参见 https://docs.particular.net/nservicebus/sagas/)。您可以在不同的存储介质(SQL、Mongo 等)中使用 saga 数据和持久化检查点。但是,是的,拥有一些长 运行ning 然后将消息从 Saga 发送到各个处理程序绝对是我也会做的事情。

另外需要考虑的是消息延迟(超时管理器)。因此,例如,假设您处理 x 个用户,但想再次 运行 。 NServiceBus 允许您将消息延迟一段定义的时间,并且消息将位于队列中等待发送。

有更多信息就大声说出来,我可以更新我的答案。

我不会为此使用传奇。 Sagas 应该是轻量级的,并且专为编排而不是执行工作而设计。它们是由消息启动的,而不是按计划启动的。

您可以使用内置的 scheduler 来达到您的目的。我没用过,但看起来很简单。

你可以这样做:

  1. 配置每天 0300 发送的命令消息(例如 StartJob)。
  2. StartJob 处理程序随后将查询数据库以获取工作。

然后,根据您的要求:

  • 如果您需要一次完成所有工作,请创建一个包含所有工作的命令,然后将其发送到另一个端点进行处理。如果您使用事务性 MSMQ,那么这将作为一个整体成功或失败。
  • 如果您不关心是否只有部分工作成功,则为每个工作单元创建一个命令,然后分派到端点进行处理。这样做的好处是,如果需要,您可以使用 distributor 进行横向扩展。

I'm working on a project that is using NSB...We have a job that needs to run every day...

尽管您可以使用 NSB 来完成此类工作,但我真的不会这样做。您可以使用许多其他方法。 SQL 作业或 cron 作业将是显而易见的(并且开发速度更快、性能更高且更简单)。

尽管它确实支持此类用例,但 NServiceBus 并不是真正为计划的批处理而设计的。我会严重质疑你是否应该使用 NSB 来完成这项任务。

一个 真正的 NSB 解决方案是摆脱 "batch" 处理一个 运行 中所有这些记录的作业,并找出什么操作( s) 最终会导致这些记录中的每一个都需要处理。

执行此类操作时,您应该发布 NSB 事件并将批处理作业重构为订阅这些事件的 NSB 处理程序,以便它可以在执行操作时进行处理,运行ning与您的其余流程并行。

这样就不再需要凌晨 3 点的预定 'start' 消息了,因为所有工作都已经完成了。

以下是我如何使用 NServiceBus 进行惯用建模:可能有一个名为 PointsExpirationPolicy 的传奇,它会在用户获得任何积分时启动。 saga 将存储用户 ID 和奖励的积分数,并计算 date/time 积分应该过期的时间。然后它将请求在 date/time 这些点应该过期时发送超时回调消息。当回调到达时,saga 发送一条命令使用户帐户中的点数过期。这也会让您在积分何时以及如何过期的逻辑上有一些灵活性,并且会消除整个批处理过程。