0

我正在对使用 2 个超时的传奇进行一些压力测试。在测试期间,大约创建了 21K saga。所以这意味着 42K 超时,但我注意到传奇的 timeoutsdispatcher 队列被成千上万的消息淹没,直到它崩溃,因为达到了 MSMQ 存储限制。

自从我将持久性机制从 RavenDB 切换到 SQL Server 后,我就看到了这种行为。

有谁知道可能出了什么问题?

传输:MSMQ
持久性:NHibernate 使用的包:

NHibernate version 4.0.4.4000  
NServiceBus version 5.2.14  
NServiceBus.Host version 6.0.0  
NServiceBus.Log4Net version 1.0.0  
NServiceBus.NHibernate version 6.2.7  

测试设置:
* 端点 1 正在向端点 2 发送 22000 条消息。
* 端点 2 托管由该消息启动的 saga。
* 每个 saga 发布一个事件,然后请求 2 次超时:1 次在 4 分钟,1 次在 10 分钟。

观察到的行为:
* 端点 1 在一分钟内发送了 22K 条消息。
* 端点 2(传奇)每秒处理 5 到 10 条消息。
* 4 分钟后第一次超时被触发,而端点 2 仍在处理来自其队列的消息,因此仍在创建新的 saga 实例。
* 从那一刻起,saga 端点的 timeoutsdispatcher 队列被消息填满。
* 大约 10 分钟后,timeoutsdispatcher 队列已经包含超过 170K 的消息并且仍在填满。
* 这种情况一直持续到端点 2 崩溃,因为达到了 MSMQ 存储限制,或者输入队列中的所有消息都已处理。如果后者先发生,则 timeoutsdispatcher 队列消息计数开始减少,直到最终达到 0。

4

1 回答 1

3

您是否使用 RavenDB 执行了相同的压力测试?SQL Server 是否在一台功能或多或少同样强大且具有快速驱动器的机器上?

更新

一些检查你的传奇

  • 是否使用了 [Unique] 属性并且使用得当?换句话说,您是否为每条传入消息使用唯一的 ID?这样每条产生 2 次超时的传入消息都会创建一个唯一的 saga 实例吗?如果每个传入的消息都访问同一个 Saga,这将是一个极大限制吞吐量的好案例。想象一下 Saga 实例已经创建过一次,否则解释会变得很复杂。于是 Message1 进来了,试图在数据库中找到行,找到并锁定它。第二条消息同时进来,找到了行但它被锁定了。它将进入重试。Message3 直到 Message100 进来(如果并发设置为 100)并且都尝试做同样的事情,立即失败。你可以看到这会限制吞吐量一段时间:)
  • 您的 Saga 表和超时表上的索引是否正确?
  • 您的最大并发级别设置为多少?

根据消息的数量,您说您发送了 22k 条消息,导致 44k 条超时消息。图像所有这些超时都在 MSMQ 中。想象一下消息非常非常小,比如 1Kb。NServiceBus 添加的头信息可能会占用 2Kb。3Kb 大约是 135 兆字节的 44.000 倍。因此,无法填满默认配额为 1GB 的默认 MSMQ 安装。

这可能意味着您的死信队列已完全填满。查找有关 MSMQ 连接字符串的更多信息并设置适当的连接字符串。例如

<connectionStrings>
  <add name="NServiceBus/Transport"
    connectionString="deadLetter=false;journal=false;"/>
</connectionStrings>

具有TimeToBeReceived属性集(链接)的消息最终进入死信队列。此外,清除队列将使所有消息进入死信队列。除非您设置正确的连接字符串。

于 2016-04-26T11:08:41.893 回答