Chapter 5. Windows Azure Storage Part II – Queues

The Windows Azure Queue service is an Internet-scale message queuing system for cross-service communications. Even though the service is called a queue, the messages aren't guaranteed to follow the First In First Out (FIFO) pattern. The design focus of the Queue service is on providing a highly scalable and available asynchronous message communication system that's accessible anywhere, anytime. The Queue service provides a REST API for applications to use the large-scale Queue service infrastructure.

The Queue service is scoped at the account level. So, when you create an account on the Azure Services Developer Portal, you get access to the Queue service. Figure 5-1 illustrates the Azure Services Developer Portal page for the storage account that I created in the previous chapter and URL endpoint for the Queue service.

Queue endpoint URL

Figure 5.1. Queue endpoint URL

The account endpoint for the Queue service is <account name>.queue.core.windows.net, where <account name> is the unique name you created for your storage account. The secret key associated with the account provides security for accessing the storage account. You can use the secret key to create a Hash-based Message Authentication Code (HMAC) SHA256 signature for each request. The storage server uses the signature to authenticate the request.

Note

HMAC is a message-authentication code calculated from the secret key using a special cryptographic hash function like MD5, SHA-1, or SHA256. The Windows Azure Storage service expects the SHA256 hash for the request. SHA256 is a 256-bit hash for the input data.

Queue Limitations and Constraints

Even though the Queue service provides a scalable and highly available infrastructure for asynchronous message communications in the cloud, it has some limitations and constraints that are important to understand before diving deep into architecture and programming. The limitations of the Queue service are as follows:

  • The Queue service supports an unlimited number of messages, but individual messages in the Queue service can't be more than 8KB in size.

  • The FIFO behavior of the messages sent to the Queue service isn't guaranteed.

  • Messages can be received in any order.

  • The Queue service doesn't offer guaranteed-once delivery. This means a message may be received more than once.

  • Messages sent to the Queue service can be in either text or binary format, but received messages are always in the Base64 encoded format.

  • The expiration time for messages stored in the Queue service is seven days. After seven days, the messages are garbage-collected.

Queue Service Architecture

The Queue service architecture consists of a three-level hierarchy: accounts, queues, and messages, as shown in Figure 5-2.

Queue service architecture

Figure 5.2. Queue service architecture

Your Windows Azure storage account is the entry point to the Queue service via the REST API.

Windows Azure Storage Account

A Windows Azure storage account encompasses the Blob, Queue, and Table services. The URI scheme for accessing the Queue service via your storage account is

<http|https>://<account name>.queue.core.windows.net

where <account name> is the unique name you created for your storage account. The <account name> must be globally unique.

For example, the Queue service for the storage account that I created in the previous chapter can be referenced as

<http|https>://proazurestorage.queue.core.windows.net

Queues

A queue is a logical destination for sending messages. There can be any number of queues in an account in the Queue service. A queue stores messages and makes them available to applications via the REST API. Queues can have metadata in the form of name-value pairs up to 8KB in size per queue. The Queue service support only private access; that means you need to have account privileges in order to access queues in a Queue service.

You can access a queue using the URI

<http|https>://<account name>.queue.core.windows.net/<queue name>

where <queue name> is the name of the queue you want to access.

For example, if you create a queue named logsqueue in the proazurestorage account, you can reference it using the following URI:

<http|https>://proazurestorage.queue.core.windows.net/logsqueue

The naming constraints for a queue are as follows:[7]

  • The queue name must be a valid DNS name.

  • Queue names must be unique within an account.

  • Queue names must start with a letter or a number.

  • Container names can't contain any special characters other than the dash (-) character.

  • The dash (-) character must be immediately followed by a character or a number.

  • All the characters in the queue name must be lowercase.

  • Queue names can't be less than 3 or more than 63 characters in length.

If a queue name or the URI violates the naming convention, an HTTP status code 400 (Bad Request) is returned by the server.

Messages

Messages are stored in queues. There is no limit to the number of messages that can be stored in a queue, but the size of each individual message can't exceed 8KB. To communicate large object messages, you can put the large object in a blob and then send the URI of that object as a message to a queue.

When you send a message, it can be in either text or binary format; but when you receive a message from the queue, it's always in Base64-encoded format. A GUID MessageID assigned by the Queue service uniquely identifies a message in the queue.

A message has the following attributes:

  • MessageID: Uniquely identifies a message in a queue and is created by the Queue service when you send the message to the Queue service.

  • PopReceipt: –An attribute of the message used for deleting or popping the message out from the queue.

  • Visibilitytimeout: An integer value representing the visibility of the message in seconds after it's received by a receiving application. The default visibilitytimeout value is 30 seconds, which means that after a message is received, it remains invisible to other applications for 30 seconds (unless it's deleted by the receiving application). The maximum visibilitytimeout value is 2 hours. The visibilitytimeout value is passed to the Queue service while a message is being retrieved from a queue.

  • Messagettl: An integer value representing the time-to-live value in seconds. When you send a message to a queue, you can specify the messagettl, which instructs the Queue service to keep the message only for the specified number of seconds. The default value for messagettl is 7 days. That means if you don't specify a messagettl value, the Queue service keeps the message for 7 days before it's garbage-collected.

You can access messages in a queue using the following URI

<http|https>://<account name>.queue.core.windows.net/<queue name>/messages

where <queue name> is the unique name of the queue within the scope of the account specified in the URI, and messages is a constant string representing all the messages in the specified queue. For example, if you create a queue named logsqueue, you can get messages from it by calling the following URI:

<http|https>://proazurestorage.queue.core.windows.net/logsqueue/messages

REST API

The REST API for the Queue service is available at the account, queue, and message levels. In this section, you learn about the Queue service REST API with specific examples. You also learn to interact with the Queue service programmatically, and you explore the queue methods in the available storage client libraries.

The REST API enables you to make HTTP calls to the Queue service and its resources. REST is an HTTP-based protocol that lets you specify the URI of the resource as well as the function you want to execute on the resource. Every REST call involves an HTTP request to the storage service and an HTTP response from the storage service.

Note

Due to frequent changes to the Windows Azure Storage service API, the URL parameters may not be exactly the same as the most recent API version. But conceptually, the variation in the REST API shouldn't be significant. For the exact parameter lists, please refer to the Windows Azure SDK documentation shipped with the SDK.

Request

The Queue service REST API's HTTP request components are described in the following sections.

HTTP Verb

The HTTP verb represents the action or operation you can execute on the resource indicated in the URI. The Queue service REST API supports the following verbs: GET, PUT, POST, HEAD, and DELETE. Each verb behaves differently when executed on a different resource.

Request URI

The request URI represents the URI of a resource you're interested in accessing or executing a function on. Example resources in the Queue service include accounts, queues, and messages. An example URI for creating a queue named logsqueue in an account named proazurestorage is

PUT http://proazurestorage.queue.core.windows.net/logsqueue

The HTTP berb PUT instructs the service to create the queue, and the URI points to the resource that needs to be created.

URI Parameters

The URI parameters are the extra parameters you specify to fine-tune your operation execution. They may include operation parameters or filter parameters for the results. In the Queue service API, the URI parameters depend on the type of resource and the HTTP verb used. For example, a URI for retrieving a list of queues from an account looks like this:

GET http://proazurestorage.queue.core.windows.net/?comp=list

The HTTP verb GET instructs the Queue service to retrieve results, and the parameter ?comp=list specifies that the data requested is a list of queues.

Request Headers

Request headers follow the standard HTTP 1.1 name-value pair format. Depending on the type of request, the header may contain security, date/time, metadata, or instructions embedded as name-value pairs. In the Storage service REST API, the request header must include the authorization information and a Coordinated Universal Time (UTC) timestamp for the request. The timestamp can be in the form of either an HTTP/HTTPS Date header or the x-ms-Date header.

The authorization header format is as follows:

Authorization="[SharedKey|SharedKeyLite] <Account Name>:<Signature>"

Where SharedKey|SharedKeyLite is the authentication scheme, <Account Name> is the storage service account name, and <Signature> is an HMAC of the request computed using the SHA256 algorithm and then encoded by using Base64 encoding.

To create the signature, you follow these steps:

  1. Create the signature string for signing. The signature string for the Storage service request consists of the following format:

    VERB
    
    Content - MD5
    
    Content - Type
    
    Date
    
    CanonicalizedHeaders
    CanonicalizedResource

    where VERB is the uppercase HTTP verb such as GET, PUT, and so on; Content — MD5 is the MD5 hash of the request content; CanonicalizedHeaders is the portion of the signature string created using a series of steps described in the "Authentication Schemes" section of the Windows Azure SDK documentation (http://msdn.microsoft.com/en-us/library/dd179428.aspx); and CanonicalizedResource is the storage service resource in the request URI. The CanonicalizedResource string is also constructed using a series of steps described in the "Authentication Schemes" section of the Windows Azure SDK documentation.

  2. Use the System.Security.Cryptography.HMACSHA256.ComputeHash() method to compute the SHA256 HMAC-encoded string.

  3. Use the System.Convert.ToBase64String() method to convert the encoded signature to Base64 format.

Listing 5-1 shows an example request header that sets the metadata values of a queue.

Example 5.1. Request Header

PUT /myfirstazurequeue?comp=metadata&timeout=30 HTTP/1.1
x-ms-date: Wed, 17 Jun 2009 04:33:45 GMT
x-ms-meta-createdBy: tejaswi
x-ms-meta-creationDate: 6/16/2009
Authorization: SharedKey proazurestorage:
     spPPnadPYnH6AJguuYT9wP1GLXmCjn0I1S6W2+hzyMc=
     Host: proazurestorage.queue.core.windows.net
Content-Length: 0

In listing 5-1, the request header consists of x-ms-date, x-ms-version, x-ms-[name]:[value] and Authorization values. x-ms-date represents the UTC timestamp, and x-ms-version specifies the version of the storage service API you're using. x-ms-version isn't a required parameter, but if you don't specify, you have to make sure the operation you're calling is available in the default version of the Queue service. Before making the REST call, be sure you match the operation you're calling with the API version it's supported in. It's always safe to match the operation with the version to get the expected results. The x-ms-meta values represent the queue metadata name-value pairs the operation should set. The last header value is the Authorization SharedKey used by the Storage service to authenticate and authorize the caller.

Note

Unlike the Blob service REST API, the Queue service REST API doesn't support HTTP 1.1 conditional headers.

Request Body

The request body consists of the contents of the request operation. Some operations require a request body, and some don't. For example, the Put Message operation request body consists of the message data in XML format, whereas the Get Messages operation requires an empty request body.

Response

The HTTP response of the Queue service API typically includes the following components.

Status Code

The status code is the HTTP status code that indicates the success or failure of the request. The most common status codes for the Queue service API are 200 (OK), 201 (Created), 204 (No Content), 400 (BadRequest), 404 (NotFound), and 409 (Conflict).

Response Headers

The response headers include all the standard HTTP 1.1 headers plus any operation-specific headers returned by the Queue service. The x-ms-request-id response header uniquely identifies a request. Listing 5-2 shows an example response header for a List Queues operation.

Example 5.2. List Queues Response Header

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/xml
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: ccf3c21c-7cca-4386-a636-7f0087002970
Date: Tue, 16 Jun 2009 04:47:54 GMT

Response Body

The response body consists of data returned by the operation. This data is specific to each operation. For example, the List Queues operation returns the list of queues in an account, whereas the Get Messages operation returns the messages in a queue. Listing 5-3 shows an example of the response body for a List Queues operation. The response contains four queues.

Example 5.3. List Queues Response Body

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults AccountName="http://proazurestorage.queue.core.windows.net/">
<MaxResults>50</MaxResults>
<Queues>
<Queue>
<QueueName>testq</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq</Url>
</Queue>
<Queue>
<QueueName>testq1</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq1</Url>
</Queue>
<Queue>
<QueueName>testq2</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq2</Url>
</Queue>
<Queue>
<QueueName>testq3</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq3</Url>
</Queue>
</Queues>
<NextMarker />
</EnumerationResults>

Tip

To test the REST API, I recommend using the Fiddler Tool available at www.fiddler2.com/fiddler2/. In this book, I use this tool to trace client/server communications.

Storage Client APIs

Even though the REST API and the operations in the REST API are easily readable, the API doesn't automatically create client stubs like the ones created by WDSL-based web services. You have to create your own client API and stubs for REST API operations. This makes the client programming more complex and increases the barrier to entry for developers. To reduce this barrier to entry, the Windows Azure SDK team has created two client helper libraries: Microsoft.WindowsAzure.StorageClient from Windows Azure SDK, and the Storage Client code sample. Both libraries are used to invoke REST APIs of the Windows Azure Storage service. The Microsoft.WindowsAzure.StorageClient library abstracts this by providing a closed-source interface and therefore is less interesting to developers who want to see the inner workings of the method calls.

In the Windows Azure CTP version, a code sample named Storage Client became the choice of developers for calling storage services because the Microsoft.WindowsAzure.StorageClient wasn't available and also because it was open source. It provided good insight into building your own storage client library. The Storage Client made it easier to see the end-to-end method calls to the Storage service. This chapter uses the Storage Client code sample in sample applications and covers the class structure and calling mechanisms in the Microsoft.WindowsAzure.StorageClient namespace.

The following sections cover the queue storage APIs from Microsoft.WindowsAzure.StorageClient and the Storage Client code sample.

Note

You don't have to use the Storage Client to make REST calls to the Storage service. You can create your own client library for making REST operations to the Storage service. In order to keep the book conceptual, I use the Storage Client code sample helper library to interact with the Storage service throughout this book. The source code for Storage Client is available in the samples directory of the Windows Azure SDK or from the Windows Azure code samples site, http://code.msdn.microsoft.com/windowsazuresamples.

Windows Azure Storage Client Queue API

The Microsoft.WindowsAzure.StorageClient namespace consists of classes representing the entire queue hierarchy. Figure 5-3 illustrates the core classes for programming Queue service applications.

Queue class hierarchy

Figure 5.3. Queue class hierarchy

As shown in Figure 5-3, four core classes are required for queue operations. Table 5-1 lists these classes and a short description of each of them.

Tip

The Windows Azure Storage Client API is the recommended method for programming Storage service applications. The API provides synchronous as well as asynchronous methods for interacting with the Storage service REST API.

Table 5.1. Classes for the Queue Service

Class Name

Description

CloudStorageAccount

A helper class for retrieving account information from the configuration file or creating an instance of the storage account object from account parameters.

CloudQueueClient

A wrapper class for getting references to the core queue objects. The class consists of methods like GetQueueReference() and ListQueues().

CloudQueue

Consists of queue operations like Create(), Delete(), AddMessage(), and GetMessage().

CloudQueueMessage

Represents a queue message with properties like InsertionTime, ExpirationTime, NextVisibleTime, Id, and PopReceipt.

In addition to these core classes, classes like QueueAttributes and QueueErrorCodeStrings represent more details about the queue.

The steps for programming simple queue applications with the queue classes listed in Table 5-1 are as follows:

  1. Add the following using statement to your C# class:

    using Microsoft.WindowsAzure.StorageClient;
  2. Instantiate the CloudStorageAccount class from the configuration file:

    CloudStorageAccount  storageAccountInfo =
    CloudStorageAccount.FromConfigurationSetting(configurationSettingName);

    Or, instantiate the CloudStorageAccount class using account information:

    CloudStorageAccount  storageAccountInfo = new CloudStorageAccount(new
    StorageCredentialsAccountAndKey(accountName, accountKey), new Uri
    (blobEndpointURI), new
    Uri(queueEndpointURI), new Uri(tableEndpointURI));
  3. Create an instance of CloudQueueClient:

    CloudQueueClient queueStorageType = storageAccountInfo. CreateCloudQueueClient ();

When you have an instance of the CloudQueueClient class, you can execute operations on the queue storage service as follows:

  • List queues:

    IEnumerable<CloudQueue> queues = queueStorageType.ListQueues();
    Create Queue
    queueStorageType.GetQueueReference(queueName).Create();
    Delete Queue
    queueStorageType.GetQueueReference(queueName).Delete();
  • Add a message:

    public void AddMessage(string queueName, CloudQueueMessage queueMessage)
    {
    queueStorageType.GetQueueReference(queueName).AddMessage(queueMessage);
    }
  • Get messages:

    queueStorageType.GetQueueReference(queueName).GetMessages
    (numberofMessages, TimeSpan.FromSeconds(visibilityTimeoutInSecs));
  • Peek messages:

    queueStorageType.GetQueueReference(queueName).PeekMessages(numberofMessages);
  • Delete a message:

    public void DeleteMessage(string queueName, CloudQueueMessage queueMessage)
    {
    queueStorageType.GetQueueReference(queueName).DeleteMessage(queueMessage);
    }
  • Set queue metadata:

    public void SetQueueMetadata(string queueName, NameValueCollection queueProps)
    {
    
    CloudQueue queue = queueStorageType.GetQueueReference(queueName);
    queue.Attributes.Metadata = queueProps;
    queue.SetMetadata();
    }

    The call to SetMetadata() method calls the method on the queue service API in the cloud.

Storage Client Code Sample Queue API

The Storage Client project consists of five important classes in the context of the Queue service. Table 5-2 lists these classes and a short description of each of them.

Table 5.2. Storage Client classes for the Queue Service

Class Name

Description

StorageAccountInfo

A helper class for retrieving account information from the configuration file.

QueueStorage

An abstract class that has properties and methods at the account level of the Queue service hierarchy. It has an AccountName property and the method ListQueues().

QueueStorageRest

A class that extends the QueueStorage class and implements the abstract methods. This class also has a nested class ListQueueResult, representing the results returned by the Queue service.

MessageQueue

An abstract class with signatures for the queue and message operations. Some example method calls are CreateQueue(), PutMessage(), and GetMessages().

QueueRest

A class that extends the MessageQueue class and implements the abstract methods.

Figure 5-4 illustrates the five classes listed in Table 5-2 and the relationships between them.

StorageClient classes for the Queue service

Figure 5.4. StorageClient classes for the Queue service

Following are some of the typical steps required to interact with the Queue service using Storage Client classes.

  1. Add your account information in the <appSettings> section of your application configuration file (app.config or web.config):

    <add key = "AccountName" value="[Your Account Name]"/>
    <add key = "AccountSharedKey"
    value="[Your Account Shared Key from the Developer Portal]"/>

    To work with local storage, add "devstoreaccount1" as the AccountName and "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" as the shared key.

  2. Add the Queue service endpoint URI in the appSettings section of your application configuration file:

    <add key="QueueStorageEndpoint" value="http://blob.core.windows.net"/>

    To work with local storage, add the URI of the local Queue service resource, http://127.0.0.1:10001.

  3. Create an instance of the StorageAccountInfo class from the configuration information you entered in the configuration file:

    StorageAccountInfo account =
    StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration();
  4. Create an instance of the QueueStorage class based on the account object:

    QueueStorage queueStorage = QueueStorage.Create(account);
  5. Call the ListQueues() method on the queueStorage object to get a list of all the queues in the account:

    queueStorage.ListQueues();
  6. To access a particular queue, call

    MessageQueue messageQueue = queueStorage.GetQueue(queueName);

    When you have a reference to the message queue object, then you can call not only queue methods like CreateQueue(), DeleteQueue(), and ListQueues(), but also message functions like PutMessage(), GetMessages(), and DeleteMessage().

In the next few sections, you learn how to call some of these functions at every level of the Queue service hierarchy.

Account Operations

The storage account provides an entry point to the Queue service via the Queue service endpoint URI. At the account level of the hierarchy, the Queue service supports only one operation: List Queues. The URI of a specific account is of the format <account name>.queue.core.windows.net. Table 5-3 describes the List Queues operation, and Table 5-4 lists some important characteristics of the List Queues function.

Table 5.3. Queue Account Operation

Operation

Description

List Queues

This operation gets the list of all the queues in a storage account. You can limit the number of records returned by specifying a filter on queue names and the size of the data set in the request. Table 5-4 lists all the possible URI parameters for this operation.

Table 5.4. Queue Account Operations Characterstics

Operation

HTTP Verb

Cloud URI

Development Storage URI

HTTP Version

Permissions

List Queues

GET

account name>.queue.core.windows.net?comp=list

http://127.0.0.1:10001/<devstorageaccount>?comp=list

HTTP/1.1

Only the account owner can call this operation.

<account name> is the storage account name, such as proazurestorage; and <devstorageaccount> is the account name for the development storage. The HTTP verb used in this operation is GET. The table lists the URI format for accessing the cloud Queue service as well as the development storage URI. Port 10001 is the default Queue service port in the development fabric.

The URI for the List Queues operation supports additional optional parameters, as listed in Table 5-5.

Table 5.5. List Queues URI Parameters

Parameter

Description

Example

prefix

A filter parameter for returning queues starting with the specified prefix value.

http://proazurestorage.queue.core.windows.net/?comp=list&prefix=may returns queues with names starting with the prefix "may".

marker

Used for paging queue results when all results aren't returned by the Storage service either due to the default maximum results allowed (the current default is 5000), or because you specify the maxresults parameter in the URI. The marker prefix is opaque to the client application.

http://proazurestorage.queue.core.windows.net/?comp=list&prefix=may&marker=/proazurestorage/testq

maxresults

The maximum number of queues the Queue service should return. The default value is 5000. The server returns HTTP Bad Request (400) code if you specify a maxresults value greater than 5000.

http://proazurestorage.queue.core.windows.net/?comp=list&prefix=may&maxresults=10

The sample REST request for List Queues in raw format looks like Listing 5-4.

Example 5.4. List Queues REST Request

GET /?comp=list&prefix=test&maxresults=50&timeout=30 HTTP/1.1
x-ms-date: Wed, 27 May 2009 04:33:00 GMT
Authorization: SharedKey proazurestorage:GCvS8cv4Em6rWMuCVix9YCsxVgssOW62S2U8zjbIa1w=
Host: proazurestorage.queue.core.windows.net
Connection: Keep-Alive

The characteristics of the REST request in Listing 5-4 are as follows:

  • The parameter comp=list at the account level of the Queue service yields the list of all the queues.

  • The prefix=test filters the results by queue names starting with "test".

  • The maxresults=50 returns 50 queues or less.

  • The x-ms-date is the UTC timestamp of the request.

  • The Authorization header contains the SharedKey of the request.

  • The Host header points to the Queue service in the cloud.

Because the request is sending a maxresults parameter, it makes sense to keep the HTTP connection alive because it's highly likely that the user will retrieve the next set of results by making another call to the Queue service.

Listing 5-5 shows the response for the List Queues request.

Example 5.5. List Queues REST Response

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: dde8c8bd-121d-4692-a578-d8fac08e4525
Date: Wed, 17 Jun 2009 01:24:45 GMT
Content-Length: 648

<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults AccountName="http://proazurestorage.queue.core.windows.net/">
<Prefix>test</Prefix>
<MaxResults>50</MaxResults>
<Queues>
<Queue>
<QueueName>testq</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq</Url>
</Queue>
<Queue>
<QueueName>testq1</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq1</Url>
</Queue>
<Queue>
<QueueName>testq2</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq2</Url>
</Queue>
<Queue>
<QueueName>testq3</QueueName>
<Url>http://proazurestorage.queue.core.windows.net/testq3</Url>
</Queue>
</Queues>
<NextMarker />
</EnumerationResults>

In Listing 5-5, the header consists of the HTTP status (200 OK) indicating the success of the operation. The response body is in XML format with <EnumerationResults /> as the root element. The <Queues /> element contains the retrieved queues. The Queue element encompasses queue attributes like the queue name and the queue URI. An empty <NextMarker /> element indicates that all the results have been retrieved.

To help you understand the Queue service programming model, open the Windows Azure Storage Operations project from Ch4Solution.sln. The project consists of a Windows form and uses the StorageClient project from the same solution for making calls to all the Windows Azure storage. The StorageClient project is shipped with the Windows Azure SDK. I also created a helper class named WindowsAzureStorageHelper in the ProAzureCommonLib project for wrapping the StorageClient methods. Figure 5-5 shows the user interface for the Windows Azure Storage Operations application as it pertains to the Operations account of the Queue service.

Windows Azure storage Queue service account operations

Figure 5.5. Windows Azure storage Queue service account operations

In Figure 5-5, the top Account section displays the account name and SharedKey of the storage account. When the Windows Azure Storage Operations.exe application starts, it loads the account information from the configuration file. Listing 5-6 shows the account configuration in the project's app.config file.

Example 5.6. App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key ="AccountName" value="proazurestorage"/>
    <add key ="AccountSharedKey" value="RyyGrNJ4z5tViRWKR3QOJAK"/>
    <add key="BlobStorageEndpoint" value="http://blob.core.windows.net"/>
    <add key="QueueStorageEndpoint" value="http://queue.core.windows.net"/>
    <add key="TableStorageEndpoint" value="http://table.core.windows.net"/>
    <add key="LocalStorageAccountName" value="devstoreaccount1"/>
  </appSettings>
</configuration>

The AccountName and AccountSharedKey values are loaded when the application starts and displays these values in the Account and Key text fields, respectively. When you start the application, make sure to enter the account name and shared key of your storage account. The QueueStorageEndpoint is the URI of the Queue service.

The WindowsAzureStorageHelper class in ProAzureCommonLib project has a ListQueue() method for retrieving queue names. Listing 5-7 shows the code for ListQueues() method.

Example 5.7. ListQueues() Method

public IEnumerable<MessageQueue> ListQueues(string prefix)
{
        if (string.IsNullOrEmpty(prefix))
{
         return this.QueueStorageType.ListQueues();
        }
        else
        {
         return this.QueueStorageType.ListQueues(prefix);
         }
}

In Listing 5-7, the ListQueues() method calls the ListQueues() method on the QueueStorageType object, which is of type QueueStorage from the StorageClient assembly. In the QueueStorage class, there are two overloaded ListQueues() methods. The first one returns all the queues in an account, whereas the second one accepts a prefix as a filter term for filtering the queues by names. Figure 5-6 illustrate the execution of the ListQueues operation in the Windows Azure Storage Operations application.

List Queues operation

Figure 5.6. List Queues operation

When you click the List Queues button, the application retrieves queues from the Queue service and displays the names of queues in the Queues ListBox. In the parameter section, you can specify the prefix.

Figure 5-7 is a sequence diagram for the ListQueues() method.

List Queues sequence diagram

Figure 5.7. List Queues sequence diagram

In Figure 5-7, the Windows Azure Storage Operations application calls the ListQueues() method on the WindowsAzureStorageHelper object in the ProAzureCommonLib assembly. The helper object then calls the ListQueues() method on the QueueStorage and QueueStorageRest objects. QueueStorage is an abstract class, and QueueStorageRest inherits and implements the abstract methods from QueueStorage. The ListQueues() method in turn calls the private method ListQueuesImpl(). Finally, the actual logic for making the HTTP request to the Queue service is in the ListQueuesImpl() method. The Queue service returns the list of queues in an HTTP response, which is parsed and propagated back to the Windows Azure Storage Operations application for display.

Queue Operations

Queues support several operations, as listed in Table 5-6.

Table 5.6. Queue Operations

Operation

Description

Create Queue

Creates a new queue under the given account. You can specify metadata for the queue during creation.

Delete Queue

Marks the specified queue for deletion. The garbage collector deletes marked queues on a periodic basis. So, if you delete a queue and try to create it immediately, the Queue service complains that the queue already exists.

Get Queue Metadata

Gets the user-defined queue metadata and other queue properties. The metadata is retrieved in the form of name-value pairs.

Set Queue Metadata

Sets the metadata values of the specified queue. Set Queue Metadata replaces all the metadata of the specified queue with new values.

Table 5-7 lists some of the important characteristics of the queue operations listed in Table 5-6.

Table 5.7. Queue Operations Characterstics

Operation

HTTP Verb

Cloud URI

Development Storage URI

HTTP Version

Permissions

Create Queue

PUT

http://<accountname>.queue.core.windows.net/<queuename>

http://127.0.0.1:10001/<devstorageaccount>/<queuename>

HTTP/1.1

Only the account owner can call this operation.

Delete Queue

DELETE

http://<accountname>.queue.core.windows.net/<queuename>

http://127.0.0.1:10001/<devstorageaccount>/<queuename>

HTTP/1.1

Only the account owner can call this operation.

Get Queue Metadata

GET/HEAD

http://<accountname>.queue.core.windows.net/<queuename>?comp=metadata

http://127.0.0.1:10001/<devstorageaccount>/<queuename>?comp=metadata

HTTP/1.1

Only the account owner can call this operation.

Set Queue Metadata

PUT

http://<accountname>.queue.core.windows.net/<queuename>?comp=metadata

http://127.0.0.1:10001/<devstorageaccount>/<queuename>?comp=metadata

HTTP/1.1

Only the account owner can call this operation.

Table 5-7 lists the HTTP verb, cloud URI, development storage URI, HTTP version, and access control for the queues. The <account name> is the storage account name in the cloud, and the <devstorageaccount> is the development storage account. Observe that unlike blob containers, all the operations can be called only with the account owner privileges.

The following sections discuss some of the operations from Table 5-7 in detail. Even though the operations are different, the programming concepts behind them are similar. To keep the book at a conceptual level, I discuss just the Create Queue and Set Queue Metadata operations. By studying these operations in detail, you can understand the programming concepts behind all the queue operations. The Windows Azure Storage Operations application included with this chapter's source code contains an implementation of all the queue operations.

Create Queue

The Create Queue operation creates a queue in a storage account. The URI for the Create Queue operation is of the format account name>.queue.core.windows.net/<queue name>. You can think of Queue as a message queuing system in the cloud. For example, if you want to send and receive messages across diverse applications in different domains, Windows Azure Queue may fit your requirement. Because of its standard REST interface and Internet scale, you can send and receive queue messages anywhere, anytime, and in any programming language that supports Internet programming. The Create Queue REST request looks like Listing 5-8.

Example 5.8. Create Queue REST Request

PUT /myfirstazurequeue?timeout=30 HTTP/1.1
x-ms-date: Wed, 17 Jun 2009 03:16:12 GMT
Authorization: SharedKey proazurestorage:a0EQSlfMdXfFrP/wwdfCUVqMYiv4PjXesF0Jp4d71DA=
Host: proazurestorage.queue.core.windows.net
Content-Length: 0

Listing 5-8 shows the request for creating a queue named myfirstazurequeue. The PUT HTTP verb instructs the Queue service to create a queue. There is no metadata information for the queue, so the queue is created without any metadata. You can add x-ms-meta-[name]:[value] to the header to create metadata values. For the Create Queue operation, the Queue service responds with a status code of HTTP/1.1 201 Created, or HTTP/1.1 409 Conflict if a queue with the same name already exists. The Create Queue response is shown in Listing 5-9.

Example 5.9. Create Queue REST Response

HTTP/1.1 201 Created
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 8b4d45c8-2b5d-46b8-8e14-90b0d902db80
Date: Wed, 17 Jun 2009 03:17:57 GMT
Content-Length: 0

In Listing 5-9, the first line represents the status code of the operation. The x-ms-request-id represents a unique request identifier that can be used for debugging or tracing.

Figure 5-8 shows the working of the Create Queue operation in the Windows Azure Storage Operations application.

Create Queue from Windows Azure Storage Operations.exe

Figure 5.8. Create Queue from Windows Azure Storage Operations.exe

As shown in Figure 5-8, to create a queue, you need to do the following:

  1. Go to the Queue Operations tab.

  2. Enter a queue name (such as myfirstazurequeue) in the Queue Name text field.

  3. Select the Create Queue operation from the Operations list box.

  4. Click the Execute button. After the queue is created, the queues list box in the Account section is refreshed with the newly created queue name in it.

To help you understand the programming model of the Create Queue operation, open the Visual Studio Solution Chapter4.sln from the Chapter 4 source directory. The WindowsAzureStorageHelper class in the ProAzureCommonLib contains a helper function called CreateQueue, as shown in Listing 5-10.

Example 5.10. Create Queue Method in the WindowsAzureStorageHelper Class

public bool CreateQueue(string queueName, out bool alreadyExists)
{
alreadyExists = false;
MessageQueue q = QueueStorageType.GetQueue(queueName);
return q.CreateQueue(out alreadyExists);
}

As shown in Listing 5-10, the CreateQueue() method calls the GetQueue() method to get a reference to the MessageQueue object. The MessageQueue object is a local instance of the Queue object. This instance doesn't create a queue when you instantiate it. To create a queue, you have to call the CreateQueue() method on the MessageQueue object. The MessageQueue object is used by the StorageClient to create accurate URI and metadata headers and send them to the Queue service. Figure 5-9 illustrates the sequence of method calls across different objects and assemblies for the Create Queue operation.

Create Queue sequence diagram

Figure 5.9. Create Queue sequence diagram

As shown in Figure 5-9, the Windows Azure Storage Operations application calls the CreateQueue() method on the WindowsStorageHelper object in the ProAzureCommonLib.dll. The WindowsStorageHelper object calls the GetQueue() method on the QueueStorage object to get an instance of the MessageQueue object. The WindowsStorageHelper object then calls the CreateQueue() method on the MessageQueue object. The CreateQueue() method creates the REST message and sends it synchronously to the Windows Azure Queue service to create the queue. It uses the System.Net.HttpWebRequest to send the REST message over HTTP. Upon success or failure of the operation, the Windows Azure Queue service returns an HTTP status code: HTTP/1.1 201 for success or HTTP/1.1 409 for conflict or failure. The CreateQueue() method translates the HTTP status code into true for success and false for failure or conflict. The Boolean value is passed all the way to the Windows Azure Storage Operations application as a return parameter of the CreateQueue() method.

Set Queue Metadata

Queues can contain name-value pairs of metadata values. You can store values like the time of creation, creator, last modified by user, and so on in the metadata fields of a container. The size of the metadata can be 8KB per queue. The Set Queue Metadata operation sets the metadata of a queue independently. The URI for the Set Queue Metadata operation is of the format account name>.queue.core.windows.net/<queue name>?comp=metadata. The Set Queue Metadata REST request looks like Listing 5-11.

Example 5.11. Set Queue Metadata REST Request

PUT /myfirstazurequeue?comp=metadata&timeout=30 HTTP/1.1
x-ms-date: Wed, 17 Jun 2009 04:33:45 GMT
x-ms-meta-createdBy: tejaswi
x-ms-meta-creationDate: 6/16/2009
Authorization: SharedKey proazurestorage:spPPnadPYnH6AJguuYT9wP1GLXmCjn0I1S6W2+hzyMc=
Host: proazurestorage.queue.core.windows.net
Content-Length: 0

In Listing 5-11, the HTTP verb used is PUT, and the URI parameter is ?comp=metadata. This parameter instructs the Queue service to set the queue metadata instead of creating the queue. The Create Queue operation doesn't have this parameter. The x-ms-meta.[name]:[value] entries represent the metadata name-value pairs you want to set on the queue.

Warning

Set Queue Metadata operation replaces all the existing metadata of the queue. It doesn't update individual metadata entries. For example, if a queue has two metadata values Creator and Creation-Time, and you call Set Queue Metadata with only one metadata value LastUpdatedBy, then the Creator and Creation-Time values will be deleted and the queue will have only one metadata value: LastUpdatedBy. To avoid this side effect, always set all the metadata values again along with any new values you want to add to the queue's metadata.

Figure 5-10 illustrates how to execute the Set Queue Metadata operation in Windows Azure Storage Operations application.

Set Queue Metadata in the Windows Azure Storage Operations application

Figure 5.10. Set Queue Metadata in the Windows Azure Storage Operations application

As shown in Figure 5-10, to execute the Set Queue Metadata operation, you do the following:

  1. Go to the Queue Operations tab.

  2. In the Account section, click the List Queues button to get a list of queues in your account.

  3. Select one of the queues from the list (such as myfirstazurequeue).

  4. Make sure the Queue Name text box in the Queues section displays the name of the selected queue.

  5. In the Queues section, select the Set Queue Metadata operation from list of queue operations.

  6. In the Queues section, enter metadata name-value pairs in the Metadata section.

  7. Click the Execute button to execute the operation.

  8. To verify the success of the operation, click the Clear Results button in the Queues section, and re-select the queue from the Queues list in the Account section to retrieve the newly set metadata values.

To help you understand the programming model of the Set Queue Metadata operation, open the Visual Studio Solution Chapter4.sln from the Chapter 4 source directory. The WindowsAzureStorageHelper class in the ProAzureCommonLib contains a helper function called SetQueueProperties(), as shown in Listing 5-12.

Example 5.12. SetQueueProperties Method in the WindowsAzureStorageHelper Class

public bool SetQueueProperties(string queueName, QueueProperties queueProps)
{
MessageQueue q = QueueStorageType.GetQueue(queueName);

return q.SetProperties(queueProps);
}

In Listing 5-12, the SetQueueProperties() method accepts the name of the queue and a QueueProperties object populated with metadata name-value pairs. The QueueProperties class has a property Metadata of type System.Collections.Specialized.NameValueCollection, which represents the metadata name-value pairs. The queue name is used to create a local instance of the MessageQueue object. The code then calls the SetProperties() method on the MessageQueue object to set the metadata values for the queue. If the metadata is set successfully, a Boolean value of true is returned back to the caller; otherwise, a false value is returned. Figure 5-11 illustrates the sequence of method calls across different objects and assemblies for the Set Queue Metadata operation.

Set Queue Metadata sequence diagram

Figure 5.11. Set Queue Metadata sequence diagram

As shown in Figure 5-11, the Windows Azure Storage Operations application calls the SetQueueProperties() method on the WindowsStorageHelper object in the ProAzureCommonLib.dll. The WindowsStorageHelper object calls the GetQueue() method on the QueueStorage object to get an instance of the MessageQueue object. The WindowsStorageHelper object then calls the SetProperties() method on the MessageQueue object. The SetProperties() method creates the REST message and sends it synchronously to the Windows Azure Queue service to set the queue metadata values. It uses the System.Net.HttpWebRequest to send the REST message over HTTP. Upon success or failure of the operation, the Windows Azure Queue service returns an HTTP status code: HTTP/1.1 200 for success or HTTP/1.1 204 (No content). The SetProperties() method translates the HTTP status code into true for success and false for failure. The Boolean value is passed all the way to the Windows Azure Storage Operations application as a return parameter of the SetQueueProperties() method.

Message Operations

Messages support several operations, as listed in Table 5-8.

Table 5.8. Messages Operations

Operation

Description

Put Message

En-queues a message at the end of the specified queue. The message can't be more than 8KB in size.

Get Messages

Dequeues one or more messages from the front of the specified queue. The maximum number of messages that can be retrieved in a single call is 32. The messages received are marked invisible until the visibilitytimeout property of the message expires. The default visibilitytimeout is 30 seconds, and the maximum value is 2 hours.

Peek Messages

Reads one or more messages from the front of the specified queue. This method doesn't alter the visibilitytimeout property of a message, so the messages are visible to other applications at the same time.

Delete Message

Deletes the specified message from the queue. The Queue service marks the message for deletion, and the message is deleted during the next garbage-collection cycle. The delete operation requires the MessageId and PopReceipt of the message to be passed to the Queue service.

Clear Messages

Deletes all messages from the specified queue.

Table 5-9 lists some of the important characteristics of the message operations.

Table 5.9. Message Operations Characterstics

Operation

HTTP Verb

Cloud URI

Development Storage URI

HTTP Version

Permissions

Put Message

POST

http://<accountname>.queue.core.windows.net/<queuename>/messages

http://127.0.0.1:10001/<devstorageaccount>/<queuename>/messages

HTTP/1.1

Only the account owner can call this operation.

Get Messages

GET

http://<accountname>.queue.core.windows.net/<queuename>/messages

http://127.0.0.1:10001/<devstorageaccount>/<queuename>/messages

HTTP/1.1

Only the account owner can call this operation.

Peek Messages

GET

http://<accountname>.queue.core.windows.net/<queuename>/messages?peekonly=true

http://127.0.0.1:10001/<devstorageaccount>/<queuename>/messages?peekonly=true

HTTP/1.1

Only the account owner can call this operation.

Delete Message

DELETE

http://<accountname>.queue.core.windows.net/<queuename>/<messageid>?popreceipt=[popreceiptvalue]

http://127.0.0.1:10001/<devstorageaccount>/<queuename>/<messageid>?popreceipt=[popreceiptvalue]

HTTP/1.1

Only the account owner can call this operation.

Clear Messages

DELETE

http://<accountname>.queue.core.windows.net/<queuename>/messages

http://127.0.0.1:10000/<devstorageaccount>/<queuename>/messages

HTTP/1.1

Only the account owner can call this operation.

The <account name> is the storage account name in the cloud, and the <devstorageaccount> is the development storage account. The <queue name> is the name of the queue in which messages are stored. The following sections discuss some of the operations from Table 5-9 in detail. Even though the operations are different, the programming concepts behind them are similar. To keep the book at a conceptual level, I discuss just the Put Message and Get Messages operations. By studying these two operations in detail, you can understand the programming concepts behind all the message operations. The Windows Azure Storage Operations application included with this chapter's source code contains implementations of most of the message operations.

Put Message

The Put Message operation en-queues (puts) a message at the end of the queue. The URI of a Put Message operation is of the format account name>.queue.core.windows.net/<queue name>/messages. You can send a message with size up to 8KB. To send larger files, you can save the message as a blob and send the URI of the blob to the queue. The body of the message while sending can be text or binary, but it should support inclusion in an XML body with UTF-8 encoding. This is because a message received from the queue is always returned in Base64-encoded format within an XML response body. You see this in the Get Messages operation. The URI for the Put Message operation supports an additional optional parameter, listed in Table 5-10.

Table 5.10. Put Message URI Parameter

Parameter

Description

Example

messagettl

This is an integer value of seconds representing the time-to-live for a message in the queue before it's retrieved or deleted. The default and the maximum value for messagettl is 7 days, after which the message is garbage-collected.

account name>.queue.core.windows.net/<queuename>/messages?messagettl=60

The Put Message REST request looks like Listing 5-13.

Example 5.13. Put Message REST Request

POST /myfirstazurequeue/messages?messagettl=120&timeout=30 HTTP/1.1
x-ms-date: Thu, 18 Jun 2009 05:52:00 GMT
Authorization: SharedKey proazurestorage:Ahv5yhR9xOrHiMTnq3fBcaBKL8KeUFQ3r
Host: proazurestorage.queue.core.windows.net
Content-Length: 84
Expect: 100-continue

<QueueMessage>
<MessageText>bXlmaXJzdGF6dXJlbWVzc2FnZQ==</MessageText>
</QueueMessage>

In Listing 5-13, a string message "myfirstazuremessage" is sent to the queue named myfirstazurequeue. The time-to-live seconds for the message is 120, which means if the message isn't received or deleted by an application within 120 seconds in the queue, the message will be marked for deletion and won't be visible to any applications. The request body consists of the message content wrapped in the <QueueMessage> element. Note that the content of the message within the <MessageText /> element is in Base64-encoded format. Listing 5-14 shows the response from the Queue service.

Example 5.14. Put Message REST Response

HTTP/1.1 201 Created
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: e724cc82-3d21-4253-9317-3b3964374be7
Date: Thu, 18 Jun 2009 05:53:32 GMT
Content-Length: 0

As shown in Listing 5-14, the Queue service responds with an HTTP/1.1 201 Created status code for a successful Put Message operation. Figure 5-12 shows the working of the Put Message operation in the Windows Azure Storage Operations application.

Put Message in Windows Azure Storage Operations.exe

Figure 5.12. Put Message in Windows Azure Storage Operations.exe

As illustrated in Figure 5-12, you can send a text message using the Windows Azure Storage Operations application. The steps for sending a message to a queue are as follows:

  1. Create a new queue (called myfirstazurequeue).

  2. Select the new queue from the Queues List Box in the Accounts section.

  3. Add some text to the Message Body text box in the Queues section.

  4. Select the Put Message operation from the Operations text box.

  5. Make sure the Queue Name text box is populated with the selected queue name.

  6. Optionally, you can specify the time-to-live in the "Time to live (secs)" text box.

  7. Click the Execute button to execute the Put Message operation.

To help you understand the programming model of the Put Message operation, open the Visual Studio Solution Chapter4.sln from the Chapter 4 source directory. The WindowsAzureStorage.cs file in the Windows Azure Storage Operations project consists of a PutMessage() method, as shown in Listing 5-15.

Example 5.15. PutMessage() Method in WindowsAzureStorage.cs

private void PutMessage()
        {
            string messageBody = string.Empty;
            if (txtMessageBody.Text.Length > 0)
            {
                messageBody = txtMessageBody.Text;

            }
            else
            {
                messageBody = String.Format
("Message from Windows Azure Storage Operations",
System.Guid.NewGuid().ToString("N"));
            }
            int ttlsecs = 300;
            if(txtTimeTolive.Text.Length > 0)
            {
                ttlsecs = int.Parse(txtTimeTolive.Text);
            }
            if (StorageHelper.PutMessage(txtQueueName.Text, new
 Microsoft.Samples.ServiceHosting.StorageClient.Message(messageBody), ttlsecs))
            {
                statusLabel.Text = String.Format
("Message {0} sent successfully to queue {1}", messageBody, txtQueueName.Text);

            }
        }

As shown in Listing 5-15, the PutMessage() method calls the PutMessage() operation on the WindowsAzureStorageHelper (StorageHelper object). The message body and the time-to-live values are parsed appropriately from the server controls and passed as parameters to the method. If you don't enter a message in the Message Body text box, the application automatically creates a default message for you. Figure 5-13 shows the sequence of Put Message operation from the application to the Queue service as it passes through various assemblies and objects.

Put Message sequence diagram

Figure 5.13. Put Message sequence diagram

As shown in Figure 5-13, the Windows Azure Storage Operations application calls the PutMessage() method on the WindowsStorageHelper object in the ProAzureCommonLib.dll. The WindowsStorageHelper object calls the GetQueue() method on the QueueStorage object to get an instance of the MessageQueue object. The WindowsStorageHelper object then calls the PutMessage() method on the MessageQueue object. The PutMessage() method of the MessageQueue object creates the REST message request and sends it synchronously to the Queue service. It uses the System.Net.HttpWebRequest to send the REST message over HTTP. Upon the success of the operation, the Queue service returns an HTTP status code: HTTP/1.1 201 Created. The PutMessage() method translates the HTTP code into true for success and false for failure. The Boolean value is passed all the way to the Windows Azure Storage Operations application as a return parameter of the PutMessage() method.

Get Messages

In the previous section, you learned to send messages to queues in the Queue service. In this section, you learn to retrieve these messages using the Get Messages operation. The URI for the Get Messages operation is of the format account name>.queue.core.windows.net/<queue name>/messages. The URI for the Get Messages operation supports additional optional parameters, as listed in Table 5-11.

Table 5.11. Get Messagse URI Parameters

Parameter

Description

Example

numofmessages

An integer value specifying the total number of messages you want retrieved. You can retrieve a maximum of 32 messages in a single call. By default, the operation retrieves only one message at a time.

account name>.queue.core.windows.net/<queue name>/messages?numofmessages=10

visibilitytimeout

An integer value representing the visibility of the message in seconds after it's received by a receiving application. The default visibilitytimeout value is 30 seconds, which means that after a message is received, it will remain invisible to other applications for 30 seconds, unless it's deleted by the receiving application. The maximum visibilitytimeout value is 2 hours.

account name>.queue.core.windows.net/<queue name>/messages?visibilitytimeout=60

Listing 5-16 shows the REST API request for the Get Messages operation.

Example 5.16. Get Messages REST Request

GET /myfirstazurequeue/messages?numofmessages=10&visibilitytimeout=60&timeout=30_
 HTTP/1.1
x-ms-date: Thu, 18 Jun 2009 05:34:13 GMT
Authorization: SharedKey proazurestorage:qB9P717GTC6nd6rX4Ed16r6QkxO2QwJxLcr
Host: proazurestorage.queue.core.windows.net

In Listing 5-16, the URI points to the myfirstazurequeue queue. numofmessages=10 instructs the Queue service to retrieve only 10 messages. visibilitytimeout=60 instructs the Queue service to make the retrieved messages invisible to other applications for 60 seconds, unless the receiving application deletes them. Listing 5-17 shows the REST API response from the Queue service for the Get Messages operation.

Example 5.17. Get Messages REST Response

HTTP/1.1 200 OK
Content-Type: application/xml
Server: Queue Service Version 1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: c10542ae-fa9e-45fd-b036-3f0b77ed611e
Date: Thu, 18 Jun 2009 05:35:43 GMT
Content-Length: 3900

<?xml version="1.0" encoding="utf-8"?>
<QueueMessagesList>
<QueueMessage>
<MessageId>ba16723c-8b4c-48dd-9d80-d5d2731bcbd8</MessageId>
<InsertionTime>Thu, 18 Jun 2009 05:36:43 GMT</InsertionTime>
<ExpirationTime>Thu, 18 Jun 2009 05:37:28 GMT</ExpirationTime>
<PopReceipt>AgAAAAEAAAAAAAAAIBeHw9bvyQE=</PopReceipt>
<TimeNextVisible>Thu, 18 Jun 2009 05:36:43 GMT</TimeNextVisible>
<MessageText>bXlmaXJzdGF6dXJlbWVzc2FnZQ==</MessageText>
</QueueMessage>
<QueueMessage>
<MessageId>c0d92c72-2f9f-4c15-a177-7cf988c2532d</MessageId>
<InsertionTime>Thu, 18 Jun 2009 05:36:43 GMT</InsertionTime>
<ExpirationTime>Thu, 18 Jun 2009 05:37:28 GMT</ExpirationTime>
<PopReceipt>AgAAAAEAAAAAAAAAIBeHw9bvyQE=</PopReceipt>
<TimeNextVisible>Thu, 18 Jun 2009 05:36:43 GMT</TimeNextVisible>
<MessageText>bXlmaXJzdGF6dXJlbWVzc2FnZQ==</MessageText>
</QueueMessage>
<QueueMessage>
<MessageId>f3ae9ccd-b97c-4bae-bc22-744cadd2c9c0</MessageId>
<InsertionTime>Thu, 18 Jun 2009 05:36:43 GMT</InsertionTime>
<ExpirationTime>Thu, 18 Jun 2009 05:37:28 GMT</ExpirationTime>
<PopReceipt>AgAAAAEAAAAAAAAAIBeHw9bvyQE=</PopReceipt>
<TimeNextVisible>Thu, 18 Jun 2009 05:36:43 GMT</TimeNextVisible>
<MessageText>bXlmaXJzdGF6dXJlbWVzc2FnZQ==</MessageText>
</QueueMessage>
</QueueMessagesList>

Listing 5-17 shows the HTTP header and body of the Get Messages operation response. For the sake of brevity, only three messages are shown. The HTTP response body consists of a list of messages in XML format. Every <QueueMessage /> element represents a message. When you retrieve a message, the MessageId and the PopReceipt properties of the message are important for deletion purposes. The recommended pattern is to receive the message, process it, and then delete it before it becomes visible to other applications when the visibilitytimeout period expires. The TimeNextVisible value specifies the expiration time of the visibilitytimeout period. The ExpirationTime specifies the time when the message will be marked for deletion if not retrieved and/or deleted by a receiving application. This value was set when the message was sent to the queue. Figure 5-14 shows the working of the Get Messages operation in the Windows Azure Storage Operations.exe application.

Get Messages in the Windows Azure Storage Operations application

Figure 5.14. Get Messages in the Windows Azure Storage Operations application

As illustrated in Figure 5-14, you can use the Get Messages operation for a queue using the Windows Azure Storage Operations application. The steps for retrieving messages are as follows:

  1. Select a queue (such as myfirstazurequeue) that already contains some messages.

  2. In the Queues section, select the Get Messages operation.

  3. Click the Execute button to get a list of messages from the selected queue.

  4. Optionally, you can specify the Number of Messages and Visibility Timeout in the Parameters section.

The retrieved messages are populated in the DataGridView control in the Messages section. Each message is represented by a row in the DataGridView control. The control displays all the properties of the retrieved messages. To delete a message, select a row in the DataGridView and press the Delete button on your keyboard.

To help you understand the programming model of the Get Messages operation, open the Visual Studio Solution Chapter4.sln from the Chapter 4 source directory. The WindowsAzureStorage.cs file in the Windows Azure Storage Operations project consists of a GetMessages() method, as shown in Listing 5-18.

Example 5.18. GetMessages() Method in WindowsAzureStorage.cs

private void GetMessages()
{
dgvMessages.Rows.Clear();
IEnumerable<Microsoft.Samples.ServiceHosting.StorageClient.Message>
 msgs = StorageHelper.GetMessages(txtQueueName.Text, int.Parse(txtNumberOf
Messages.Text), int.Parse(txtVisibilityTimeoutSecs.Text));

if (msgs != null)
{
IList<Microsoft.Samples.ServiceHosting.StorageClient.Message> messages =
new List<Microsoft.Samples.ServiceHosting.StorageClient.Message>(msgs);
PopulateMessagesDataGridView(messages);

}
}

As shown in Listing 5-18, the GetMessages() method calls the GetMessages() method of WindowsAzureStorageHelper (StorageHelper object). The numofmessages and visibilitytimeout parameters are parsed appropriately into integer values and passed as parameters to the GetMessages() method. The returned messages are then packaged into a list and passed to the PopulateMessagedataGridView() method for display. Figure 5-15 illustrates the sequence diagram for the Get Messages operation.

Get Messages sequence diagram

Figure 5.15. Get Messages sequence diagram

As shown in Figure 5-15, the Windows Azure Storage Operations application calls the GetMessages() method on the WindowsStorageHelper object in the ProAzureCommonLib.dll. The WindowsStorageHelper object calls the GetQueue() method on the QueueStorage object to get an instance of the MessageQueue object. The WindowsStorageHelper object then calls the GetMessages() method on the MessageQueue object. The MessageQueue object calls a private method InternalGet() to retrieve the messages from the specified queue. The body of the HTTP response contains messages in XML format. The XML contents are parsed and packaged into an IEnumerable<Message> collection and passed as a return parameter to the GetMessages() operation. Finally, the Windows Azure Storage Operations application displays these messages in a DataGridView control, as shown earlier in this section.

Message Event

The StorageClient API also supports an event-driven model for retrieving messages from a queue. The MessageQueue class defines an event called MessageReceived that you can subscribe to. The MessageQueue class also defines two methods StartReceiving() and StopReceiving() that start and stop the event subscription, respectively. The property PollInterval specifies the polling interval in milliseconds. Based on the PollInterval value, a thread calls the Get Messages operation periodically and returns the messages as parameters of the event delegate.

The steps for implementing an event-driven approach to the Get Messages operation are as follows.

  1. Create an instance of the MessageQueue object:

    Microsoft.Samples.ServiceHosting.StorageClient.MessageQueue mq =
    StorageHelper.GetQueue(txtQueueName.Text);
  2. Create an event handler for the MessageReceived event:

    mq.MessageReceived += new MessageReceivedEventHandler(mq_MessageReceived);

    1. The event handler method signature for mq_MessageReceived has MessageReceivedEventArgs as one of the parameters, which has a Message property representing the retrieved message.

  3. Set the PollInterval property of the MessageQueue object to the desired polling interval in milliseconds:

    mq.PollInterval = 10000;
  4. Start receiving messages by calling the StartReceiving() method:

    mq.StartReceiving();
  5. To stop receiving messages, call the StopReceiving() method:

    mq.StopReceiving()

Note

The even-driven model is a purely client-side implementation for ease of client programming. In the background, the event is fired periodically and calls the same Get Messages operation discussed in this section. The REST API for the Queue service doesn't offer asynchronous invocations.

Queue Scenarios

In the previous sections, you saw the details of working with the Windows Azure Queue service. This section covers some of the basic application communication scenarios that can use the Windows Azure Queue service.

Scenario 1: Windows Azure Web and Worker Role Communications

Consider a scenario in which you're designing an ecommerce web application in Windows Azure with a Web Role front end and several Worker Roles for back-end processing work. The Web Role instances continuously send purchase order information to the Worker Roles for order processing. In this scenario, you can use the Windows Azure Queue service to queue purchase order messages for the Worker Roles, as shown in Figure 5-16.

Web Role/Worker Role communication using the Queue service

Figure 5.16. Web Role/Worker Role communication using the Queue service

In Figure 5-16, Web Role instances 1 and 2 send orders to the order-processing queue. Worker Roles 1 and 2 dequeue the order messages and process the orders. Because not all orders have to be processed immediately, Worker Roles can pick up from the queue only the orders that are ready to be processed. This way, you can create an effective message communication system between Web Roles and Worker Roles, taking advantage of the scalable and highly available Queue service infrastructure. If the order message size exceeds 8KB, you can store the message body in the Blob service and pass a link to the blob as a queue message, as shown in Figure 5-16. When the Worker Role dequeues the message, it can retrieve the contents of the order from the Blob service.

Scenario 2: Worker Role Load Distribution

Continuing Scenario 1, depending on the volume of messages, you can either adjust the number of queues or the number of instances of Worker Roles for processing orders. For example, if you identify during your testing phase that one Worker Role can process only ten orders at a time, you can configure Worker Roles to pick up only ten messages from the queue. If the number of messages in the queue keeps increasing beyond the number that Worker Roles can process, you can create more instances of Worker Roles on demand and increase the order-processing capacity. Similarly, if the queue is under-utilized, you can reduce the Worker Role instances for processing orders.

In this scenario, the Queue service plays the role of capacity indicator. You can think of the queues in the Queue service as indicators of the system's processing capacity. You can also use this pattern to process scientific calculations and perform business analysis. Figure 5-17 illustrates the Worker Role load-distribution scenario.

Worker Role load distribution

Figure 5.17. Worker Role load distribution

In Figure 5-17, Worker Roles 1 through 3 can process average order loads. When the number of orders backs up into the queue, you can spawn more Worker Roles (4 through n) depending on demand and the need for overall order-processing capacity.

Scenario 3: Interoperable Messaging

Large enterprises use applications from different vendors, and these applications seldom interoperate with each other. An enterprise may end up buying an expensive third-party tool that acts as the interoperability bridge between these applications. Instead, the enterprise could use the Queue service to send messages across the applications that don't interoperate with each other naturally. The Queue service exposes a REST API based on open standards. Any programming language or application capable of Internet programming can send and receive messages from the Windows Azure Queue service using the REST API. Figure 5-18 illustrates the use of the Queue service to interoperate between a Java-based Sales application and a .NET-based CRM application.

Interoperable messaging

Figure 5.18. Interoperable messaging

Scenario 4: Guaranteed Processing

In Scenario 1, every order needs guaranteed processing. Any loss in orders can cause financial damage to the company. So, the Worker Roles and the Queue service must make sure every order in the queue is processed. You can implement guaranteed processing using four simple principles:

  • Set the visibilitytimeout parameter to a value large enough to last beyond the average processing time for the messages.

  • Set the visibilitytimeout parameter to a value small enough to make the message visible if message processing fails in a consumer (Worker Role) or a consumer crashes.

  • Don't delete a message until it's processed completely.

  • Design the message consumers (Worker Roles) to be idempotent (that is, they should account for handling the same message multiple times without an adverse effect on the application's business logic).

Figure 5-19 illustrates guaranteed message processing in the context of the order-processing example discussed in Scenario 1.

Guaranteed processing

Figure 5.19. Guaranteed processing

In Figure 5-19, two Web Roles create orders, and three Worker Roles process orders. Consider the following steps:

  1. Worker Role 1 reads order O1 for processing. Worker Roles typically take 15 seconds to process an order. The visibilitytimeout for messages is set to 60 seconds.

  2. Worker Role 1 starts processing order O1. At this point, O1 isn't visible to other Worker Roles for 60 seconds.

  3. Worker Role 1 crashes after 10 seconds.

  4. After 60 seconds, O1 becomes visible again because Worker Role 1 wasn't able to delete it.

  5. Worker Role 2 reads O1 and processes it.

  6. After processing is complete, Worker Role 2 deletes O1 from the queue.

The important points to note here are that Worker Role 1 didn't delete the message from the queue before processing was complete, and the visibilitytimeout was set to an appropriate time window to exceed the processing time of an order.

Queue Summary

The Queue service provides a scalable and highly available store and delivery mechanism for exchanging messages across distributed applications. It provides reliable message delivery from message producers to message consumers. The Queue service exposes a REST API, making it easily accessible across multiple platforms and programming languages. In the previous section, you saw some of the important operations and scenarios for using the Queue service. The next chapter covers Windows Azure tables.

Bibliography

MSDN. (n.d.). ADO.NET Data Services Specification. Retrieved from MSDN Developer's Network: http://msdn.microsoft.com/en-us/library/cc668808.aspx.

MSDN. (2009, May). Windows Azure Blob — Programming Blob Storage. Retrieved from MSDN: http://go.microsoft.com/fwlink/?LinkId=153400.

MSDN. (2009, May). Windows Azure Queue — Programming Queue Storage. Retrieved from MSDN: http://go.microsoft.com/fwlink/?LinkId=153402.

MSDN. (2009, May). Windows Azure SDK. Retrieved from MSDN: http://msdn.microsoft.com/en-us/library/dd179367.aspx.

MSDN. (2009, May). Windows Azure Table — Programming Table Storage. Retrieved from MSDN: http://go.microsoft.com/fwlink/?LinkId=153401.



[7] Source: Windows Azure SDK documentation

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.72.212