C# - 限制MessageQueue

时间:2010-10-20 10:07:16

标签: c# message-queue

我的代码会将消息发送到MessageQueue

_queue.Send(new Message(myData));

此队列位于本地计算机上,并且Receive()的线程处于同一进程中。

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

谢谢, 塞拉。

2 个答案:

答案 0 :(得分:4)

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

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

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

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

祝你好运!

答案 1 :(得分: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
}