Operational costs of an Azure Message Queue
November 6, 2010 5 Comments
A potential issue with azure message queues is the fact that there are hidden costs associated with them, depending on how often the system accesses the queues you pay more, no matter whether there are messages or not.
Lets have a look at what the operational cost model for NServiceBus would look like if we treated azure queues the same as we do msmq queues.
On azure you pay $0.01 per 10K storage transactions. Every message send is a transaction, every successful message read are 2 transactions (GET + DELETE) and also every poll without a resulting message is a transaction. Multiply this by the number of roles you have, and again by the number of threads in the role and again by the number of polls the cpu can launch in an infinite for-loop per second and you’ve got yourself quite a bill at the end of the month. For example, 2 roles with 4 threads each, in idle state, at a rate of 100 polls per second would result in an additional $2.88 per hour for accessing your queues.
Scary isn’t it 🙂
As a modern day developer you have the additional responsibility to take these operational costs into account and balance them against other requirements such as performance. In order for you to achieve the correct balance, I’ve implemented a configurable back-off mechanism in the NServiceBus implementation.
The basic idea is, if the thread has just processed a message it’s very likely that there are more messages, so we check the queue again in order to maintain high throughput. But if there was no message, we will delay our next read a bit before checking again. If there is still no message, we delay the next read a little more, and so on and so on, until a certain threshold has been reached. This poll interval will be maintained until there is a new message on the queue. Once a message has been processed we start the entire sequence again from zero…
Configuring the increment of the poll interval can be done by setting the PollIntervalIncrement property (in milliseconds) on the AzureQueueConfig configuration section, by default the interval is increased by 50 milliseconds at a time. To define the maximum wait time when there are no messages, you can configure the MaximumWaitTimeWhenIdle property (also in milliseconds). By default this property has been set to 1 second. So an idle NServiceBus role will slow down incrementally by 50 milliseconds until it polls only once every second. For our example of 2 roles with 4 threads, in idle state, this would now result in a cost of $0.0288 per hour.
Not so scary anymore 🙂
Please play with these values a bit, and let me know what you feel is the best balance between cost and performance…
Until next time…