我们要求所有消息按照到达MSMQ的顺序进行处理。
我们将向客户端公开一个WCF服务,此WCF服务将使用NServiceBus (Sendonly Bus)将消息发送到MSMQ。
我们将开发一个windows服务(MessageHandler),它将使用Nservicebus从MSMQ读取消息并将其保存到数据库中。我们的数据库每天都会有几个小时不可用。
在数据库停机期间,我们预计该进程会重试MSMQ中的第一条消息,并停止处理其他消息,直到数据库启动。一旦数据库启动,我们希望NServicebus按照消息发送的顺序进行处理。
在这种情况下,设置MaximumConcurrencyLevel="1“MaximumMessageThroughputPerSecond="1”是否有帮助?
使用NServiceBus处理此场景的最佳方式是什么?
发布于 2015-09-15 17:18:27
我们有一个要求,我们所有的消息都要按照到达消息队列的顺序处理。
查看这个问题的答案How to handle message order in nservicebus?,也可以查看这篇文章here。
我同意,虽然按顺序交付是可能的,但最好设计您的系统,使顺序无关紧要。链接的文章概述了以下解决方案:
然而,为了回答你的具体问题:
在这种情况下,
设置MaximumConcurrencyLevel="1“MaximumMessageThroughputPerSecond="1”是否有帮助?
不怎么有意思。
只要您有有序传递的需求,基本的逻辑法则就会规定,在消息处理管道中的某个地方,必须有一个单线程进程才能保证按顺序传递。
发生这种情况的地方由您决定(查看resequencer pattern),但您当然可以将NserviceBus处理程序限制为单线程(我认为您不需要设置MaximumMessageThroughputPerSecond使其成为单线程)。
但是,即使您这样做了,即使您使用了事务性队列,您仍然不能保证每条消息都会按顺序出队并处理到数据库中,因为如果任何消息出现任何永久性故障,它们都将从队列中删除并处理下一条消息。
在数据库停机期间,我们预计该进程会重试MSMQ中的第一条消息,并停止处理其他消息,直到数据库启动。一旦数据库启动,我们希望NServicebus按照消息发送的顺序进行处理。
不建议这样做。NServiceBus中的第二级重试功能旨在处理意外和短期中断,而不是计划内和长期中断。
对于初学者来说,当您的NServiceBus消息处理程序端点尝试处理其输入队列中的消息并发现数据库不可用时,它将实现其二级重试策略,该策略在默认情况下将尝试出队5次,并且频率不断增加,然后永久失败,将失败的消息保留在其错误队列中。然后,它将移动到输入队列中的下一条消息。
虽然这本身并没有违反您的订单交付要求,但由于以下两个原因,它将使您的生活变得非常困难:
如果您有预先知道的定期计划停机,那么处理它们的最简单方法是实现服务窗口,这是计划的另一个术语。
但是,windows服务管理器不支持服务窗口的概念,因此您必须使用计划任务来停止然后启动您的服务,或者查看其他选项,如hangfire、quartz.net或一些其他cron-type库。
发布于 2015-09-17 06:10:26
这在某种程度上取决于你为什么需要消息按顺序到达。如果您首先收到一条Order消息,然后又收到各种OrderLine消息,这些消息都属于某个特定的顺序,那么就有多种可能。
一种是接受没有Order也可以有OrderLine消息。无论如何,Order都会在稍后出现。最终的一致性。
另一个是收集NServiceBus传奇中的消息(和可能的状态)。通常情况下,MessageA需要先到达,然后才能收到MessageB和MessageC,让所有三个消息都有能力开始这个传奇。这三条消息都需要有某种东西将它们联系在一起,比如唯一的GUID。然后,saga将确保它正确地收集它们,并且当所有消息都已到达时,可能存储其最终状态,并将saga标记为完成。
另一种选择是将所有消息直接持久化到数据库中,然后让其他东西找出哪些消息属于哪些消息。对于数据仓库来说,这是一个很有用的场景,在这种数据仓库中,无论什么情况,都只需要收集数据。有些数据可能不是100%准确(或一致),但这是可以接受的。
异步消息使得很难按100%的顺序处理它们,特别是当调用WCF的客户端出错和/或无序发送它们时。这并不是我第一次遇到这样的要求和无序的消息。
https://stackoverflow.com/questions/32574412
复制相似问题