Are Remote MSMQ Queues Reliable?
I have played around a bit with MSMQ private queues and documented some of my findings earlier. In my first blog on this topic, I had captured how the naming of the queue is critical to connect to the right queue.
If it was local private queue, you could use - ".\\private$\\queuename"
and if it was remote private queue, you use - "FormatName:Direct=OS:machinename\\private$\\queuename"
In my second blog, I mentioned about how to receive messages from remote private queues. The key to receiving message (apart from the correct queue format name) was to have an appropriate formatter so that the messages from the queue can be read properly.
What I do find strange is that attaching a formatter isn't necessary when sending messages. If a default formatting is plugged in automatically in that case, why can't one be plugged-in in case of receiving messages. One reason, I can think of is probably the outgoing formatting is decided based on the message type being sent out. While in case of reading, you don't know what is being read and can be a security issue as well if you try to read from the queue without really knowing what to expect.
Finally, in my third blog, I discussed about how to configure and use journal queues.
What has intrigued me is some of the comments that people have raised on these blog and my own experiment results. I document them there.
When working with remote private MSMQ queues, keep in mind that they aren't 100% reliable. Well the queues as such are, but the way the .net APIs function, they appear to be not. Very simply, an application can't easily find out if a particular private queue exists on a remote machine or not. You could use the static method MessageQueue.GetPrivateQueuesByMachine() and pass the remote machine name and get the list of queues on it, but when sending a message, if for some reason, the queue has been deleted the message will still be sent from the application and it will be lost.
MessageQueue.GetPrivateQueuesByMachine() returns a MessageQueue collection and you can access the FormatName property of individual queues in this collection, to get the correct format name for the remote private queues. In case the remote machine isn't accessible when firing the MessageQueue.GetPrivateQueuesByMachine() call, a System.Messaging.MessageQueueException is raised with the following details
ErrorCode - "-2147467259"
Message - "Remote computer is not available."
MessageQueueErrorCode - System.Messaging.MessageQueueErrorCode.RemoteMachineNotAvailable
If the remote machine is accessible, but the MSMQ service isn't running on that machine, the System.Messaging.MessageQueueException is still raised, but the details become cryptic and are as below
ErrorCode - "-2147467259"
Message - null
MessageQueueErrorCode - "-2147023143"
In case either the remote machine is down or the MSMQ service on that machine isn't running, when you try to send message from your application, the message is stored on a temporary outgoing queue that is created automatically on the local machine. From the application's point of view, the message is successfully delivered. Once the remote machine is up and the MSMQ service successfully running on it, the message from the temporary outgoing queue is automatically delivered. This looks like a good feature, but this also has its own dangers and you can get surprising behaviors. This is mainly because this entire logic is based only on validating the connectivity with the remote machine and a running MSMQ service on that machine. Even if the queue to which you are trying to send the message doesn't exists, the message will still go and essentially vanish since it isn't on local machine anymore and doesn't reach the remote machine, as the queue isn't present anyway.
Another similar issue is let's say the remote queue does exists, but doesn't has write access. Even in that case, the application will successfully send messages without realizing that the message is lost. However none of these issue exist if you are working with local private queues. In such cases, invalid queue names, improper security access rights etc are all validated and appropriate exceptions raised. Hence if you are facing issues of disappearing messages when sending to remote private queues, try running the application on the remote machine itself with the queue path appropriately changed (to point to local queue). This will help identify any queue name or security issues that might be causing the disappearing messages.
Does this means that private queues aren't good to be used? Not really ! They work very well when they are local. In case of remote private queues, the infrastructure automatically doesn't support detecting all error conditions and you have to explicitly verify the right queue name and security permissions.
If you want complete infrastructure support as well for remote queues, you should be considering public queues and not private queues.