Scaling out your application is easy with Azure Service Bus, because Azure Service Bus by design lends itself well to the competing consumers pattern as described by Gregor Hohpe and Bobby Woolf in the Enterprise Integration Patterns book.
So, in order to make this post a little longer, I will tell a little bit on how Rebus makes use of Azure Service Bus. And then I’ll tell you how to scale it 🙂
Rebus and queue transactions
When Rebus is configured to use Azure Service Bus to transport messages like this:
1 2 3 4 5 |
Configure.With(yourContainerAdapter) .Logging(l => l.NLog()) .Transport(t => t.UseAzureServiceBus(connectionString, "some_input_queue", "error_queue")) .CreateBus() .Start(); |
the bus will not use Azure Service Bus queues for its input queue and error queue, as you might think.
This is because Rebus will go to great lengths to promise you that a message can be received, and 0 to many messages sent – in one single queue transaction!
This means that the underlying transport layer must somehow be capable of receiving and sending messages atomically – and in a way that can be either committed or rolled back.
And since Azure Service Bus has limited transactional capabilities that do NOT allow for sending messages to multiple queues transactionally, we had to take a different approach with Rebus.
So, how does Rebus actually use Azure Service Bus?
What Azure Service Bus DOES support though, is receiving and sending atomically within one single topic.
So when Rebus starts up with Azure Service Bus, it will ensure that a topic exists with the name “Rebus”, which will be used to publish all messages that are sent.
And then, for each logical input queue – let’s call it “some_input_queue” – there will be a subscription for that queue by the same name, and that subscription will be configured with a SqlFilter that filters the received messages on a specific message property that holds the name of the intended recipient’s input queue. The filter will then ensure that only the intended messages are received for that endpoint.
So – how to scale it?
Easy peasy – in the Azure portal, go to this section of your cloud service:
and go crazy with this bad boy:
and – there you have it! – that is how you can scale out your work with Rebus in Azure 🙂
One thing, though – when you’re doing some serious number crunching, depending on the granularity of your messages of course, you may be bitten by the fact that Azure Service Bus’ BrokeredMessage’s lease expires after 60 seconds – if that is the case, Rebus has a fairly non-intrusive way of letting you renew the lease, which you can read more about in the “more about the Azure Service Bus transport” on the Rebus wiki.
In the next post, I’ll delve into how to scale your Rebus workers if you’re using RabbitMQ.