.NET Service Bus (Part 2 continued) – Hands on Queues
August 18, 2009 3 Comments
Back again in rapid succession and feeing very strong. Over the weekend I smoked a bunch of turkey (most yummy) and also finally made my first weight loss goal. How did I decide to celebrate these accomplishments you ask…. I decided that I’d jump right back in with another blog post about .NET Service Bus queues. Yes, I’m a geek.
If you read my last post, you may recall that I said that .NSB queues were more robust and I pointed out a few key differences. Well, I was understanding things just a bit. They are actually significantly more robust and also require a few different techniques when dealing with them. In this update I will explore those differences in a bit more detail as well as cover the basics of sending and receiving messages via .NET Service Bus queues.
Queue Policy (yeah for governance)
Azure Storage queues are pretty basic. As far as I can tell, they were created to be a simple, lightweight option for doing inter-process communication. As such, they were kept pretty simple, the single-scoop vanilla ice cream of queue storage mechanism. Well the .NSB Queues are closer to what I think of as traditional queues. Each queue has a policy that dictates how the queue will behave. Here are some of the queue policy settings:
|Authorization||AuthorizationPolicy||Determines if authorization is required to send and/or receive messages to a queue.|
|Discoverability||DiscoverabilityPolicy||Is access public, or can it only be discovered by managers (default), listeners, or senders (based on Access Control Service token)|
|ExpirationInstance||DateTime||When the queue will expire. If not periodically renewed, the queue and all its messages will be deleted (unrecoverable).|
|MaxMessageAge||TimeSpan||Messages that have been in the queue in excess of the TimeSpan value are dropped. Default is 10 minutes, maximum is 7 days.|
|Overflow||OverflowPolicy||How to handle messages when the queue is full.|
|PoisonMessageDrop||EndpointAddress||Where do poison (unreadable) messages get sent?|
|TransportProtection||TransportProtectionPolicy||sets if a secure connection is required to send to or receive from this queue|
There are other properties (some of which appear to be for future use), but these are the ones I wanted to call to your attention today.
Of key interest are MaxMessageAge and PoisonMessageDrop. When you put a message into an Azure Storage queue, it stays there until either the message or the queue is removed. .NSB queues will automatically purge messages that exceed the specified TimeSpan value. And as anyone that has worked with queues will tell you, occasionally messages get “stuck” and can’t be read. So its nice to be able to using PoisonMessageDrop to specify a SOAP endpoint to which these messages can be directed.
Yeah, but how do I send/receive?
Ok, enough blabbering, this is supposed to be a hands-on blog. How about we get to some hands-on already. Any direct interaction with the queue is done via the QueueClient object. So we need to get an instance of that object for our queue before we start doing any real work. To do that we need the QueueManagementClient again.
In my last post we started by crafting our URI and creating TransportClientEndpointBehavior based credentials. We’ll need those same items this time around, but instead of calling the QueueManagementClient’s CreateQueue method with a QueuePolicy object, we’re instead going to call the GetQueue method. Here’s our code snippit:
// create queue URIUri tmpURI = ServiceBusEnvironment.CreateServiceUri("sb", SolutionName, "/" + textBox1.Text.Trim());// authenticate against the queue managerTransportClientEndpointBehavior tmpCredentials = new TransportClientEndpointBehavior();tmpCredentials.CredentialType = TransportClientCredentialType.UserNamePassword;tmpCredentials.Credentials.UserName.UserName = SolutionName;tmpCredentials.Credentials.UserName.Password = Password;QueueClient tmpQueue = QueueManagementClient.GetQueue(tmpCredentials, tmpURI);
The result is an instance of QueueClient called tmpQueue that we can now use to send/receive messages in our queue.
Sending and Receiving Messages (finally)
Alright, so now we’re ready to start sending and receiving messages. Doing this is pretty simple.
Here’s an example of a send…System.ServiceModel.Channels.Message tmpMessage =System.ServiceModel.Channels.Message.CreateMessage(MessageVersion.Default,"urn:testsend", "my message");tmpQueue.Send(tmpMessage, TimeSpan.FromSeconds(30));
Simple enough. Since I’m using a Windows Forms application as my host, I need to be careful with ambiguous references to the Message class (the Windows.Forms namespace also has such a class). I can also change the MessageVersion to “Default”. But I did some testing and Soap12WSAddressing10 works as well. So depending on your specific scenario, it could get even simpler.
Next up is reading a message…System.ServiceModel.Channels.Message tmpReadMsg = tmpQueue.Retrieve();MessageBox.Show(tmpReadMsg.GetBody<string>());
Now this is where some additional differences between Azure Storage and .NSB queues start to become apparent. The Retrieve method automatically removes the message from the queue. This differs from Azure Storage where a second call is required to remove it. Additionally, unlike Azure Storage, if we want to retrieve multiple messages, we need to use a different method (RetrieveMulitiple) to get them. However, unlike Azure Storage, the retrieval of multiple items does not appear to be limited to a maximum of 25 messages (can’t find confirmation on this though, so I’ll try to do some testing).
But… but… what about peeking?
Ok, so we want to see what’s in a queue without actually removing it. Simple enough, we just switch to the PeekLock and PeekLockMultiple methods. Notice the “Lock” adjective in both those methods names. Yes, they actually operate more like way messages are read from Azure Storage. After a PeekLock (or PeekLockMultiple), a separate call is needed to DeleteLockedMessage or ReleaseLock methods using the retrieved (or peeked) Message object. If this is not done, the peeked message will be automatically unlocked after 60 seconds. Unfortunately, unlike Azure Storage queues, there doesn’t appear to be a way to vary the timeout period.
If you’ve worked with Azure Storage queues, you’re likely feeling a bit confused right now. While Azure Storage and .NSB queues both serve a similar purposes, the actual implementations are radically different. .NSB queues offer policy enforcements, access control, and router integration. Azure Storage queues have greater persistence and flexibility in retrieval options. So you’ll need to weigh which option is best suited to your needs.
Next time, we’re going to be kicking things up yet another notch as I start into .NSB routers. Things will get really fun as we start combining queues and routers together to handle how messages get processed.