摘要(tl; dr):我们正在尝试设置一个Peek
访问但不是Receive
访问权限的队列用于测试目的(所以{{1请求将失败,但Receive
将成功),但似乎MSFT比预期更难。
后台:我们有一个本地私有MSMQ队列,一个进程从中接收并处理(/使用)消息。在某些情况下,无法完成处理并且消息保留在队列中(例如,转发目的地暂时离线)。因此,每隔约10分钟就会添加一个监视器以查看队列,并查看顶部的消息是否相同 - 如果消费者停止(同一消息位于顶部),监视器会触发警报以指示那是错的。
为了测试目的强制队列停止(为了确保监视器功能正常工作),我们认为我们只是从队列中删除(但不是拒绝)Peek
权限本身但仍然允许 Receive
(重新启动MSMQ以及强制执行新权限的所有内容),理想情况下,监视器允许Peek
消息,而不允许任何人Peek
(/删除)消息,“拖延”队列并生成警报。
然而,在测试这个场景时,我遇到了一个异常,似乎阻止了这种方法:
Receive
这表明(至少对我来说)System.Messaging.MessageQueueException: Access to Message Queuing system is denied.
at System.Messaging.MessageQueue.MQCacheableInfo.get_ReadHandle()
at System.Messaging.MessageQueue.StaleSafeReceiveMessage(UInt32 timeout, Int32 action, MQPROPS properties, NativeOverlapped* overlapped, ReceiveCallback receiveCallback, CursorHandle cursorHandle, IntPtr transaction)
at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
at System.Messaging.MessageQueue.Peek(TimeSpan timeout)
内部调用Peek()
并且必须尝试事务ReceiveCurrent()
,然后它将在完成消息后回滚/中止。启动.NET Reflector,我发现Receive
的所有实例都调用Peek
的某个变体,因此不同的Receive
无效。因此,对于Peek
来说,Receive
权限似乎是必需,就队列设计而言似乎有些愚蠢。
请注意,使用者和监视器都使用相同的帐户(/ permissions),并且此时更改监视方法(使用Peek
)不是一个可行的选项(因为需要对要求,规格和生产代码进行重大更改,而这些更改的成本将超过其价值)(尽管我猜你可以提出监控方法的变化,如果你真的必须这样做,因为如果他们遇到同样的事情他们可能对他人有用)。
最后,问题:在没有Peek
权限的情况下,队列顶部的Peek
是否有更好的(甚至是不同的:p)方式?或者以不同的方式设置权限(通过权限界面,通过代码等),使Receive
本身失败但Receive
和ReceiveCurrent
所需的其他方法有效?