【问题标题】:C# - Throttling a MessageQueueC# - 限制消息队列
【发布时间】:2011-04-27 23:05:42
【问题描述】:

我有将消息发送到MessageQueue 的代码。

_queue.Send(new Message(myData));

这个队列在本地机器上,并且来自它的Receive()的线程在同一个进程中。

如果消息的插入速度快于提取速度,会发生什么情况? Send() 会阻止吗? 有没有办法让我知道 MessageQueue 在发送更多事件之前是否已满? (此时我宁愿只记录 myData 而不发送事件)。

谢谢, 塞拉。

【问题讨论】:

  • 你能解释一下它是哪种类型的消息队列吗?又名 .Net 提供的类,在内存中,与数据存储区持久......需要更多信息来回答您的问题。
  • 这是 Windows 提供的 MSMQ。

标签: c# message-queue


【解决方案1】:

设计一个系统使得消息的产生速度不会快于它们的消费速度是好的,我同意这一点。尽管如此,可能消息的生产者会碰壁,因为队列已满,尤其是在设置的配额较低时。

要为这种情况做准备,您需要监视Send() 方法是否成功。如果您将消息发送到一个完整的队列中,则消息会丢失,并且因为Send() 返回void,所以不会立即产生成功或失败的结果。但是有一种方法可以检测到这一点。使用 MSMQ 时,您应该请求确认。要接收它们,您需要使用管理队列。通过这种方式,您可以收到有关发生的不同情况的通知,包括队列已满。

Message msg = new Message
{
    Formatter = new BinaryMessageFormatter(),
    Body = data,
    AdministrationQueue = this.adminQueue,
    AcknowledgeType = AcknowledgeTypes.FullReachQueue
};

this.queue.Send(msg);

Message admMsg = this.adminQueue.Receive();
if (admMsg != null && admMsg.Acknowledgment == Acknowledgment.QueueExceedMaximumSize)
{
    // queue is full
}

【讨论】:

    【解决方案2】:

    简答:做简单的事,不要限制发送。

    长答案: 消息队列只有在分配用于保存的磁盘空间不足时才会真正变满 - 这与您的日志记录空间不足的时间相同。消息队列非常擅长保存您尚未准备好处理的数据。不要限制发送。如果您关心系统管理和磁盘空间,那么您可能更愿意依赖 Window 出色的系统监控工具和磁盘空间使用阈值警报。您无需为您的应用程序重新发明它。

    除非您在仅内存模式下运行队列,否则可能没有必要。如果您不能足够快地处理消息,那么您肯定有足够的时间让队列管理器将消息持久保存到磁盘。如果您要扩展到许多服务器上的许多消费者进程并且队列管理器上的磁盘 IO 成为瓶颈,您应该只考虑在仅内存模式下运行队列。同一台机器上的一个进程与这种情况相去甚远。 让队列管理器做它最擅长的事情。不要过早优化。

    如果您实施指定的服务质量(例如每秒 X 条消息),并为处理更高质量的服务向客户收取更多费用,则在接收端进行节流。我已经使用初始化的信号量成功地做到了这一点,该信号量的资源限制等于每秒消耗的消息数。每个消费者线程拍摄消息开始时间的快照,处理 1 条消息,然后等待第二秒结束,然后放弃信号量。这样,如果消息处理时间超过 1 秒,线程池可以增长以适应服务质量,但不会超过服务质量。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 2016-05-06
      相关资源
      最近更新 更多