消息队列计数比较






4.91/5 (7投票s)
比较在MSMQ上计数消息的不同方法
介绍
最近我需要创建一个可视化监控多个消息队列中消息数量的手段。 这应该相对简单,创建一个UI来显示myMessageQueue.Count()
的结果,但是消息队列类中并不存在count方法。
游标方法
当我搜索解决方案时,大多数评论都在使用游标。 这是我最初使用的方法,但是当我有大约> 35,000条消息时,我发现计数非常不稳定。 队列中的消息越多,此方法花费的计数时间就越长。
有关使用游标与MSMQ的完整描述,请参阅Microsoft的http://support.microsoft.com/kb/178516。
private MessageQueue _messageQueue;
private int CountCursor()
{
_messageQueue = new MessageQueue(".\\private$\\pingpong", QueueAccessMode.Peek);
int count = 0;
Cursor cursor = _messageQueue.CreateCursor();
Message m = CursorPeekWithoutTimeout(cursor, PeekAction.Current);
if (m != null)
{
count = 1;
while ((m = CursorPeekWithoutTimeout(cursor, PeekAction.Next)) != null)
{
count++;
}
if (m != null) m.Dispose();
}
cursor.Dispose();
return count;
}
protected Message CursorPeekWithoutTimeout(Cursor cursor, PeekAction action)
{
Message ret = null;
try
{
ret = _messageQueue.Peek(new TimeSpan(1), cursor, action);
}
catch (MessageQueueException mqe)
{
if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
{
throw;
}
}
return ret;
}
GetAllMessages方法
GetAllMessages
返回队列中消息的静态副本,这对于小型的单次计数来说是可以的。在实际应用中,队列中可能存在数百万条大型消息,因此为了减少带回的信息量,我们需要设置消息过滤器。队列中的消息越多,此方法花费的计数时间就越长。
var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var countFilter = new MessagePropertyFilter
{
AdministrationQueue = false,
ArrivedTime = false,
CorrelationId = false,
Priority = false,
ResponseQueue = false,
SentTime = false,
Body = false,
Label = false,
Id = false
};
_messageQueue.MessageReadPropertyFilter = countFilter;
return _messageQueue.GetAllMessages().Length;
GetEnumerator2方法
GetEnumerator2
返回队列中消息的动态列表。 队列中的消息越多,此方法花费的计数时间就越长。
var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var x = _messageQueue.GetMessageEnumerator2();
int iCount = 0;
while (x.MoveNext())
{
iCount++;
}
return iCount;
PowerShell (WMI) 方法
这是迄今为止最快的方法,无论有多少消息需要计数,大约需要20毫秒。这是计数您有权访问的其他机器上的消息队列的唯一方法。
private int GetPowerShellCount()
{
return GetPowerShellCount(".\\private$\pingpong", Environment.MachineName, "", "");
}
private int GetPowerShellCount(string queuePath, string machine,string username, string password)
{
var path = string.Format(@"\\{0}\root\CIMv2", machine);
ManagementScope scope;
if (string.IsNullOrEmpty(username))
{
scope = new ManagementScope(path);
}
else
{
var options = new ConnectionOptions {Username = username, Password = password};
scope = new ManagementScope(path, options);
}
scope.Connect();
if (queuePath.StartsWith(".\\")) queuePath=queuePath.Replace(".\\",string.Format("{0}\\",machine));
string queryString = String.Format("SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue");
var query = new ObjectQuery(queryString);
var searcher = new ManagementObjectSearcher(scope, query);
IEnumerable<int> messageCountEnumerable =
from ManagementObject queue in searcher.Get()
select (int)(UInt64)queue.GetPropertyValue("MessagesInQueue");
//IEnumerable<string> messageCountEnumerable =
// from ManagementObject queue in searcher.Get()
// select (string)queue.GetPropertyValue("Name");
var x = messageCountEnumerable.First();
return x;
}
测试
我决定创建一个测试,该测试将计算消息数量并计算消息计数的时间。要运行源代码中包含的测试,您需要在您的机器上创建一个私有MSMQ,队列的名称无关紧要,因为应用程序将使用它找到的第一个私有队列。测试应用程序需要以管理员身份运行,因为您将在测试开始之前清除消息队列。
参考文献
- John Opincar: http://jopinblog.wordpress.com/2008/03/12/counting-messages-in-an-msmq-messagequeue-from-c/
- Emil Åström: http://www.meadow.se/wordpress/?p=648
- Microsoft: http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.getallmessages.aspx
- http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.getmessageenumerator2.aspx