Power of Windows Azure PaaS: Service Bus Sequence Counter

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

If you are distributed application developer you will probably know how often thereby any participant in the system. is a requirement to implement a sequence counter which generates a next number and can be consumed by any participant in the system.
Long time ago as we have been implementing client server architectures, this was relatively easy to achieve by using of Database sequence numbering. In the last decade of services we moved the responsibility of the counter to the service later.
That means we implemented a dedicated service which plays a role of counter generator. As following picture shows two devices consume the Sequence Generator Service.

 

image 
As long you are in control of the infrastructure and devices this is a valid solution. But what if your system is distributed across a cloud? In this case you can basically do the same way. You can create a service as a worker role (on of possibilities) and provision database (or use table storage) to store the current value of the counter.
However you can do it much simpler and even chipper way if you use Windows Azure Service Bus. Independent on lower costs, Service Bus provides notifications, high performance and  even REST access. To demonstrate this I have implemented a prototype API on top of ServiceBus library.  Following picture shows how architecture is slightly changed in a case of cloud counter, which I will call WebCounter later in tihs post.

image

In this case there is no explicite service which you have to build. In fact we will use the cloud as dependency. More precisely  we will use for this scenario Windows Azure Service Bus.

The WebCounter Api should hide ServiceBus functionality. This is because not many developers have a good understanding of messaging and bus technology. Moreover hidden details are not necessarily simple in comparison to counter scenario.
My proposed implementation look like:

WebCounter counter = new WebCounter(config parameters);
var val = counter.GetNext();


Optionally you can reset the counter:

counter.ResetValue(7);

This is in term of API more or less all. It looks very trivial and you even don’t need any documentation to start using it. This is exactly the idea of this post, to show how useful scenarios can be built by leveraging of PaaS.

How does it work?

First of all, the WebCounter API have to create the queue, which will be used to hold the counter value. To do that the initialization has to be performed:

public WebCounter(string connStr, string contextName, string counterName)


connStr is Service Bus Connection string like
Endpoint=sb://xyzuvw.servicebus.windows.net/;SharedSecretIssuer=owner;SharedSecretValue=…obfuscated.="

contextName defines the business domain of the counter like ‘MyClinicalDevicesCounter’.

counterName defines the name of sub-context inside of business context like ‘BloothTestCounter’ or ‘RentgenScanCounter’.

Service Bus would see them like: Queue with name “MyClinicalDevicesCounter/BloothTestCounter” and “MyClinicalDevicesCounter/RentgenScanCounter”.

Internally the queue will be created like shown in following snippet:

  private void createCounterQueue()
        {
           
NamespaceManager namespaceManager = NamespaceManager.CreateFromConnectionString(m_ConnStr);
           
QueueDescription desc = new QueueDescription(getQueueName());
            desc.RequiresSession =
true;

           
try
            {
               
var qD = namespaceManager.CreateQueue(desc);
            }
           
catch (Microsoft.ServiceBus.Messaging.MessagingEntityAlreadyExistsException)
           
{

            }
        }


Notice that the queue is session queue. This means that transitionally one participant can access the queue only. Because the queue will be used to hold the last counter value we are not interested on ordered deliver of the message.
If the queue with the same name already exists, we will simply ignore the exception.

Now, let’s take a look how the counter value is generated. First we create the receiver session. The receiver will either return NULL-message (very first call) ovaluer the counter value.
Then we calculate the next value (0 if this is the first message or Value++). Right after receiving the message we will immediately write the new value in the queue. Because the session receiver is opened while writing the message,
no any other client in the web can start receiving of messages. While receiving is locked the client will write the new value and so on.

Unfortunately, every client in the web will in this scenario have a possibility to send the message to the queue. In this case vendors of such clients would theoretically have a possibility to compromise the system.
As long the queue name is possibly obfuscated, the message encrypted  and client on devise safe, this could not be a big issue. Anyhow you should be aware of possible risks, at least.

Here is the code snippet which shows how counting can be implemented.

public long GetNext()
        {
           
QueueClient client = QueueClient.CreateFromConnectionString(m_ConnStr, getQueueName(), ReceiveMode.PeekLock);

           
while (true)
            {
               
MessageSession sessionReceiver = null;

               
try
                {
                    sessionReceiver = client.AcceptMessageSession(m_QueueName,
TimeSpan.FromSeconds(10));

                   
long cnt = 1;

                   
var msg = sessionReceiver.Receive(TimeSpan.FromSeconds(10));
                   
if (msg != null)
                    {
                        cnt = msg.GetBody<
long>();
                        msg.Complete();
                    }
                   
else
                    {

                    }

                    cnt++;
                    client.Send(createMessage(cnt));
                   
return cnt;
                }
               
catch (SessionCannotBeLockedException)
                {

                }
               
catch (Exception ex2)
                {
                   
throw;
                }
               
finally
                {
                   
if (sessionReceiver != null)
                       
sessionReceiver.Close();
                }
            }
        }

Here is the more illustrated recap of WebCounter implementation:


image


Posted Apr 21 2013, 05:40 PM by Damir Dobric
developers.de is a .Net Community Blog powered by daenet GmbH.