如何在不锁定队列的情况下通过NServiceBus发送大量消息?

时间:2015-06-24 03:18:49

标签: c# nservicebus

所以我正在对NServiceBus进行一些性能评估,并且我意识到如果你试图同时发送所有1000条消息,它表现得非常奇怪...它实际上发送它们所有异步(这很好)但它锁定来自处理程序的队列。结果是处理程序无法处理任何消息,直到发件人完成了所有消息的发送。

这种行为以两种略有不同的方式出现。

  • 如果你做了大量的发送,在处理程序内部,看起来接收队列被锁定,直到处理程序完成(所以说你在每次发送之间添加线程休眠,接收者不会开始处理处理程序完成之前的消息。

  • 如果我只是从一个新的公共汽车发送消息,那么一个小小的睡眠会打破这种关系,但是如果我只是在"一次"处理程序在写完最后一个之前不会获得第一个,即使每个人(在那一点上)应该是一个单独的电话。

这里是否有未记录的策略批量发送或其他事情......我知道你不会想要"要正常地做到这一点,但要了解在处理程序发送过程中发生的事情,或者从普通总线发送批量发送是非常重要的,要知道; - )。

2 个答案:

答案 0 :(得分:5)

默认情况下,NServiceBus消息处理程序包含在TransactionScope中。处理消息,您对业务数据所做的任何更新以及任何新消息的发送都将完成或回滚。这就是事务性消息传递的全部内容。

如果在消息处理程序中发送1000条消息,则在基础消息传递基础结构成功收到所有消息之前,它将无法完成。这可能需要一些时间,具体取决于您的硬件。

如果您想退出此默认安全方法,您可以执行以下操作。您可以为您的NServiceBus端点disable transactional handling,或者在发送消息时只需suppress the ambient transaction scope。但请注意,您不再拥有任何交易保证,因此如果您在发送500条消息后发送500条消息,则会发送500条消息,而500条消息则不会发送。

答案 1 :(得分:0)

我的团队策略之一是尝试将大批量分解为较小的批次,然后让一个处理程序接收这些较小的批次并为每个批次推送单个事件。

场景:我们有一个端点,它读取数据库日志文件并推出一个" TransactionOccurred"日志文件的每一行的事件。然后,我们在10秒超时后再次读取日志文件并推出另一批消息。

因此,我们不是在一个处理程序中推出5K消息,而是将其分解为5个1K的消息并发送一个命令。然后我们有一个处理程序,它接收到1K批处理消息,循环并发布每个消息的单个事件。

这个问题围绕着做一个"发布"对于5K消息,因为有几个事件正在发布,并且每个事件都有一组不同的订户,在同一服务器和远程服务器上有队列,这会减慢系统速度。

通过这种策略,我们还能够将MaximumConcurrencyLevel向上调整一次,以便一次处理多条消息,并且能够获得更高的吞吐量。

我们已经在少数端点上完成了这一点,并且每个端点在批量大小和MaximumConcurrencyLevel值方面略有不同。我建议获取50-100K消息的控制集,并将这些值稍微移动到适合您​​情况的最佳值。