Сводка (tl; dr): Мы пытаемся настроить очередь с Peek
доступом, но не Receive
доступом для целей тестирования (поэтому запрос Receive
завершится неудачно, ноPeek
будет успешным), но кажется, что MSFT сделал это более трудным, чем ожидалось.
Справочная информация: У нас есть локальная частная очередь MSMQ, из которой один процесс получает и обрабатывает (/ потребляет)) Сообщения.В некоторых ситуациях обработка не может быть завершена, и сообщение остается в очереди (например, переадресация получателя временно в автономном режиме).Поэтому был добавлен монитор, который просматривал очередь каждые ~ 10 минут и проверял, является ли сообщение вверху одинаковым или нет - если потребитель остановлен (то же сообщение вверху), монитор выдает сигнал тревоги, чтобы указать,что-то не так.
Чтобы заставить очереди останавливаться в целях тестирования (чтобы убедиться, что функция монитора работает), мы подумали, что просто удалим (но не deny ) Receive
разрешения из самой очереди, но все равно позволяют Peek
(перезапуск MSMQ и все для обеспечения новых разрешений), что в идеале позволило бы монитору 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()
и должен попробовать транзакционный Receive
, чтобы он затем откатывался / прерывался после того, как это сделаноetting сообщение.Запустив .NET Reflector, я обнаружил, что все экземпляры Peek
вызывают какой-то вариант Receive
, поэтому другой Peek
не поможет.Таким образом, похоже, что Receive
разрешения необходимы , а также Peek
, что кажется довольно глупым с точки зрения проектирования очереди.
Обратите внимание, что и потребитель, и мониториспользовать одну и ту же учетную запись (/ permissions), и изменение метода мониторинга (с использованием Peek
) на данный момент не является жизнеспособным вариантом (поскольку это потребует значительных изменений требований, спецификаций и производственного кода,будет стоить больше, чем стоит) (хотя я думаю, вы могли бы предложить изменения методологии мониторинга в любом случае, если вам действительно это нужно, поскольку они могут быть полезны для других, если они сталкиваются с тем же самым).
Наконец,Вопрос: Есть ли лучший (или даже просто другой: p) путь к Peek
в верхней части очереди без необходимости Receive
разрешений?Или другой способ установки разрешений (через интерфейс разрешений, через код и т. Д.) Таким образом, что сам Receive
завершается неудачно, но ReceiveCurrent
и другие методы, необходимые для Peek
, работают?