I have previously written about message queue systems. The big two, as far as I can see, are Active MQ and RabbitMQ.
Microsoft have always had MSMQ*, but it’s not really a message broker as such (I believe that you can get similar behaviour using NServiceBus, but have never tried that myself). However, with Azure comes the Azure Service Bus.
The first thing that you need to do is set-up an Azure account. Note that Microsoft offer Azure as a paid service, and so this is not free. However, they also offer free trials and free Azure credit if you have an MSDN.
Log on to:
Namespace
Namespaces are an important concept in Azure. They basically allow you to split a single Azure account across many functions, but what that means is that everything you do relates to a specific namespace.
To add one, first, pick a pricing tier:
Make sure that your Namepsace isn’t taken:
You’ll then get an alert to say it worked:
If you refresh, you should now see your namespace:
Create Test Project
I always try to start with a console app when trying new stuf. Add NuGet reference:
It is my understanding that, as with ActiveMQ and RabbitMQ, these client libraries are an abstraction over a set of HTTP Post calls. In the case of Azure, I believe that, behind the scenes, it uses WCF to handle all this.
Using the Namespace
Using a message queue system such as RabbitMQ or ActiveMQ, you need a message queue server, and a URL that relates to it. However, one of the things Azure allows you to do is to abstract that; for example:
static void Main(string[] args)
{
Console.WriteLine($"Getting service bus URI...");
Uri uri = ServiceBusEnvironment.CreateAccessControlUri("pcm-servicebustest");
Console.WriteLine($"Service Bus URI: {uri.ToString()}");
Console.ReadLine();
}
Tells me what the URI of the message queue broker is:
Adding a message to a queue
In order to do anything with a message queue in Azure, you need a token; effectively, this provides a level of security
Tokens
Get the key:
You can store these details in the app/web.config, or you can use them programmatically:
private static TokenProvider GetTokenProvider(Uri uri)
{
Console.WriteLine($"Getting token...");
TokenProvider tp = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", "JWh82nkstIAi4w5tW6MEj7GKQfoiZlwBYjHx9wfDqdA=");
Console.WriteLine($"Token {tp.ToString()}");
return tp;
}
Queues
Putting the above calls together, we can now create a queue in Azure:
private static void CreateNewQueue(Uri uri, TokenProvider tokenProvider)
{
Console.WriteLine($"Creating new queue...");
NamespaceManager nm = new NamespaceManager(uri, tokenProvider);
Console.WriteLine($"Created namespace manager for {nm.Address}");
if (nm.QueueExists("TestQueue"))
{
Console.WriteLine("Queue already exists");
}
else
{
Console.WriteLine("Creating new queue");
QueueDescription qd = nm.CreateQueue("TestQueue");
}
}
Incidentally, the act of creating a queue appears to have cost £0.24 GBP. If you have MSDN, you should get £40 GBP credit each month (at the time of writing).
Now we have a queue, let’s put some messages on it.
Adding a message
private static void AddNewMessage(string id, string messageBody, string queueName)
{
BrokeredMessage message = new BrokeredMessage(messageBody)
{
MessageId = id
};
string connectionString = GetConnectionString();
QueueClient queueClient = QueueClient.CreateFromConnectionString(connectionString, queueName);
queueClient.Send(message);
}
The Connection String can be found here:
We can now see that a message has, indeed, been added to the queue:
At this time, this is about as much as you can see from this portal.
Errors
These are some errors that I encountered during the creation of this post, and their solutions.
System.UnauthorizedAccessException
System.UnauthorizedAccessException: ‘The token provider was unable to provide a security token while accessing ’https://pcm-servicebustest-sb.accesscontrol.windows.net/WRAPv0.9/’. Token provider returned message: ‘The remote name could not be resolved: ‘pcm-servicebustest-sb.accesscontrol.windows.net”.’
The cause is not an invalid secret
That’s because this line:
TokenProvider tp = TokenProvider.CreateSharedSecretTokenProvider("RootManageSharedAccessKey", "jjdsjdsjk");
Gives the error:
System.ArgumentException: ‘The ‘issuerSecret’ is invalid.’
The fix…
This code is littered throughout the web:
TokenProvider tp = TokenProvider.CreateSharedSecretTokenProvider("RootManageSharedAccessKey", "jjdsjdsjk");
TokenProvider tp = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", "JWh82nkstIAi4w5tW6MEj7GKQfoiZlwBYjHx9wfDqdA=");
System.ArgumentNullException: ‘Queue name should be specified as EntityPath in connectionString.’
Or: 40400: Endpoint not found.
Microsoft.ServiceBus.Messaging.MessagingEntityNotFoundException: ‘40400: Endpoint not found., Resource:sb://pcm-servicebustest.servicebus.windows.net/atestqueue. TrackingId:48de75d7-fb01-4fa9-b72e-20a5dc090a8d_G11, SystemTracker:pcm-servicebustest.servicebus.windows.net:aTestQueue, Timestamp:5/25/2017 5:23:27 PM
Means (obviously) that the following code:
QueueClient.CreateFromConnectionString(connectionString, queueName);
Either doesn’t have the queue name, or it is wrong.
References
https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-exceptions
https://stackoverflow.com/questions/18558299/servicebus-throws-401-unauthorized-error
https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-queues-topics-subscriptions
https://msdn.microsoft.com/en-us/library/jj542433.aspx?f=255&MSPPError=-2147217396
* Microsoft probably haven’t ALWAYS had MSMQ. There was probably a time in the early 90’s where they didn’t have a message queue system at all.