【问题标题】:NServiceBus and system integration: how to handle messages properly?NServiceBus 和系统集成:如何正确处理消息?
【发布时间】:2014-10-27 20:16:45
【问题描述】:

我正在通过使用利用 MSMQ 传输层的 NServiceBus 集成两个(将来可能超过两个)系统。 我需要支持几种业务对象类型的同步(特别是来自端点端的这些对象上的创建、更新、删除事件)。 我正在使用 Pub/Sub 消息传递模式。

NSB 消息传输有关创建、更新和删除业务对象的信息。服务总线应禁止更新或删除特定端点系统中不存在的对象。

让我们考虑以下情况。 Endpoint1中有消息按以下顺序发布:

[Message1]: "create business object A"
[Message2]: "update business object A"
[Message3]: "delete business object A"

问题 1:我们不知道 Endpoint2 将按什么顺序 (a) 接收入站队列和 (b) 处理上述消息,对吗?

问题 2:如果 Message1 在 Endpoint2 中没有得到正确处理,它将被放回队列中,然后将首先处理其他消息,对吗?

问题 3:在这种情况下,Message2 和 Message3 会因为尝试对不存在的对象进行操作而报错。那我应该如何处理 Message2 和 Message3 呢?我应该为此使用 sagas 吗?

问题 4:另一个问题:如果有多个“更新对象 A”消息 - 如何确保/强制将最后一个作为最后一个处理?

【问题讨论】:

    标签: nservicebus


    【解决方案1】:

    问题 1:我们不知道 Endpoint2 将按什么顺序 (a) 接收 入站队列和 (b) 处理上述消息,对吗?

    正确。也就是说,根据您期望这些消息生成的距离有多近,它们被接收和处理乱序的可能性可能非常小。

    问题 2:如果 Message1 在 Endpoint2 中无法正确处理,则 将被放回队列中,其他消息将首先处理, 我说的对吗?

    将根据配置立即尝试 x 次(我认为默认为 5 次),然后将回退到 Second Level Retries,这将允许在此期间处理其他消息消息被延迟。

    问题 3:在这种情况下,Message2 和 Message3 会报错 因为尝试对不存在的对象进行操作。我该怎么办 那么处理Message2和Message3呢?我应该为此使用 sagas 吗?

    Sagas 绝对是一个可能的选择。工作流程是否完全创建 => 更新 => 删除?可以有多个更新吗?删除总是发生吗? Sagas 通常用于对固定/已知的工作流程进行建模,因此这可能是也可能不是最佳选择,具体取决于您的具体情况。

    问题4:另一个问题:如果有几个“更新对象A” 消息 - 如何确保/强制将最后一个处理为 最后一个?

    执行更新并发布它们的端点可能需要在消息上放置一个版本号(对于该实体实例),并且订阅者可能必须确保消息按顺序得到处理。或者,订阅者可能只需要丢弃版本号低于最后处理的消息的消息。这取决于每次更新是过渡性的还是代表状态的完全覆盖。在任何情况下,订阅端点都必须通过在本地存储版本号来以某种方式管理它。

    归根结底,所有这一切都取决于您的具体情况、您希望如何发布消息以及消息被乱序处理的后果。例如,您希望消息在 99.999% 的情况下发布的距离足够远,以至于这些都无关紧要,我不建议在这方面花费太多精力。

    如果这些确实很少见,明智地使用 Bus.Defer() 可能足以理顺消息顺序。

    我假设您将这个问题作为一般问题而不是特定场景提出,但如果您确实有要解决的特定问题,我建议您将特定场景发布到 Particular mailing list--the社区通常非常有帮助。

    【讨论】:

    • 广告。问题 3:工作流程完全是创建 => 更新 => 删除,但它可以随时停止。可以有多个更新。那么在这种情况下,sagas 会是一个不错的选择吗?
    • 我认为 sagas 在这种情况下不是一个好的选择——我认为您想要的是数据库或其他一些持久性数据存储。除非我误解了你,否则这听起来更像是永久的坚持而不是长期运行的过程。
    • 您很了解我 - 所以一种可能的解决方案是添加消息版本号(或者可能是时间戳)并在本地存储在 BusinessObjectInstanceType&Id 和 TimestampOfLastSuccessfullyHandledMessage 的数据库对中。然后,如果端点接收到一条不实际的消息(即来自本地存储的版本小于一个),则会引发异常,并在重试和 SLR 之后,将消息放入错误队列中。你觉得这有意义吗?您在这种解决方案中看到任何警告吗?谢谢。
    • 这行得通吗?是的。这是最好的解决方案吗?不知道完整的故事很难说。如果一个版本低于数据库的版本,可以忽略吗?如果您已经知道它会反复失败,那么让它重试多次是没有意义的。同样,Stack Overflow 可能不是提供详细解决方案的最佳场所——我建议您在论坛上发帖(社区非常有帮助)。
    猜你喜欢
    • 2011-06-18
    • 2011-09-15
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 2021-02-08
    相关资源
    最近更新 更多