Node.js, Windows Azure (and socket.io)

The Windows Azure Platform now supports various application-hosting environments including:

.NET has always been the primary development environment for Windows Azure. Java and PHP have been around for many years and applications developed in these environments have been deployable to Windows Azure for some time.

Node.js is a lightweight platform, developed by Ryan Dahl (@ryah), for building highly-scalable network applications written in JavaScript. In particular, it can be used to develop and deploy web servers. socket.io is a Node.js package that provides a simple way to access HTML5 web sockets thereby facilitating the creation of applications supporting browser-to-browser conversation. The Node.js documentation is here.

This post is a brief introduction to Node.js and socket.io with that introduction being focused on the implementation of Node.js inside the Windows Azure environment.

Node.js

Node.js is an application hosting environment developed in C++ and using the Google V8  JavaScript engine to host applications written in JavaScript. An essential feature of applications written in Node.js is the heavy use of callbacks making support for an asynchronous programming model more natural. Node.js can be downloaded directly from the Node.js website.

Hello World in Node.js

The following example demonstrates how easy it is to write a website serving a single Hello World web page.

var port = 81;
var http = require('http');

var app = http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
});

app.listen(port);
console.log('Server running on port ' + port);

When the above code is saved in a file named server.js the following command can be used to launch the web server:

node server.js

The require() statement imports the Node.js http module into the application where it is used to create an HTTP server. The parameter to the createServer() method is an anonymous callback function invoked each time the server receives a request. This callback is passed the request and response streams for the request. In the example, a response header is added before res.end() is invoked to write Hello World to the response and flush the response back to the client. app.listen() starts the server listening on port 81.

This simple program demonstrates several features common to Node.js applications:

  • the use of require() to import modules into the application
  • the creation of a server
  • the use of listen() to start the listening process

Application Frameworks

A web application can be coded directly in JavaScript and deployed as a website hosted in Node.js. As in other web-development environments it is common to use an application framework to structure the application and enforce a separation of concerns that aids the development of large-scale applications.

Many Node.js samples use the Express framework. This uses routes and views directories to store application routes and views. Express supports various view engines including Jade and EJS (embedded JavaScript). These provide different ways to specify the appearance of a web page.

The following commands can be invoked to download the Express module and create a default Node.js web server using the Express framework and the Jade view engine:

npm install express
.\node_modules\.bin\express
npm install

node app.js

This starts a web server, listening on port 3000, which responds with the web page defined in views\index.jade.

Node Package Manager (NPM)

The Node Package Manager (NPM) is an application that simplifies the local installation for the thousands of packages that have been created for Node.js. NPM stores downloaded packages in a node_modules folder under the invocation directory. It is possible to specify that downloaded packages be stored globally but, in general, they should be regarded as part of the application they are being used in and stored locally (which is the default).

The package.json file associated with a downloaded package specifies dependencies on other packages that it may have. NPM recursively downloads these dependent packages into a node_modules directory associated with the initial package. The NPM is invoked as follows:

npm install packageName

Windows Azure

Microsoft supports Node.js as a first-class development environment for Windows Azure. The Windows Azure developers portal has a section devoted to Node.js that contains various samples and a download link for the Windows Azure SDK for Node.js.

The SDK is installed in the following directory:

%ProgramFiles(x86)%\Microsoft SDKs\Windows Azure\Nodejs

The installation process creates a link on the Start menu for the Windows Azure PowerShell for Node.js which launches a PowerShell console with the Windows Azure Node.js cmdlets preloaded. These cmdlets can be used to manage the creation and deployment of hosted services both in the development and Windows Azure environment. As is typical with Windows Azure development environments, the PowerShell console should be launched using Run as Administrator.

The cmdlets include the following:

  • New-AzureService serviceName
  • Add-AzureNodeWorkerRole roleName
  • Add-AzureNodeWebRole roleName
  • Start-AzureEmulator
  • Stop-AzureEmulator

These can be used sequentially to create a Windows Azure hosted service with zero or more web and worker roles and then deploy them to the compute emulator before tearing down the service. The developer portal has a sample that does precisely this. Other cmdlets support the deployment of the hosted service to Windows Azure.

Web Roles and Worker Roles

The Windows Azure SDK for Node.js implements web and worker roles in different ways leading to differences in the supported functionality. Specifically, since http.sys does not support HTML5 web sockets it is not possible to use them in a Node.js (or any) application deployed to a web role. Web sockets are supported for Node.js (or any) application deployed to a worker role. One benefit of using a web role is that, as shown by Aaron Stannard (@Aaronontheweb) in this post, IIS can handle the launching of multiple node.exe instances automatically. Otherwise, Node.js would only be able to use a single core, even in a multi-core instance.

A web role is implemented using a special IISNode module which is loaded as additional ASP.NET module in IIS. When creating a Windows Azure package for deployment, the packager creates a startup task to perform various tasks including installing IISNode in the web role instance. In the development machine, IISNode is installed in:

%ProgramFiles(x86)%\Microsoft SDKs\iisnode

A worker role is implemented using the new ProgramEntryPoint functionality exposed in ServiceDefinition.csdef which allows an arbitrary program to be specified as the role entry point. Specifically, on startup a worker role hosting a Node.js application invokes the following program entry point:

node.exe .\server.js

An obvious implication is that the Node.js application must be in a file named server.js – although it can import additional modules.

It is remarkably easy to port a Node.js application to Windows Azure. A particularly impressive sample on the Windows Azure developer portal takes a standard example from the socket.io website and ports it to Windows Azure by changing only two lines of code. One change is simply to the location of a module while the other is the specification of the port to listen on in a Windows Azure friendly manner. Specifically, when using Windows Azure SDK for Node.js it is necessary to specify the listening port using:

process.env.port

which allows the application to access the correct Windows Azure endpoint.

Furthermore, it can sometimes be helpful to test Node.js applications directly, using node.exe, without launching the Windows Azure development environment. This is feasible because of the simple manner with which Node.js applications are inserted into the development environment.

Node.js Packages for Windows Azure

The Windows Azure SDK for Node.js does not provide access to the various Windows Azure SDKs. In keeping with the style of Node.js applications, this SDK is instead deployed as a set of Node.js packages for Windows Azure which are downloaded into a Node.js application using

npm install azure

The packages expose Node.js APIs for:

  • Windows Azure Storage Service (blobs, tables and queues)
  • Service Bus Brokered Messaging (queues, topics and subscriptions)

The Windows Azure developer portal has a complete example showing how to access Windows Azure Table service from a Node.js application developed using Express/Jade. When the azure packages are installed, examples of all the supported functionality are installed in the node_modules\azure\examples directory for the application.

Some Node.js on Windows Azure Links

Glenn Block (@gblock) has an interesting Channel 9 interview in which he describes Node.js on Windows Azure. Matt Harrington (@mh415) has a post describing the environment variables available when using the Node.js azure packages as well as a post showing how to log messages. Aaron Stannard has a post on using the Node.js packages for Windows Azure outside the compute emulator.

socket.io

Guillermo Rauch (@rauchg) developed socket.io, a Node.js package that simplifies the creation of web applications supporting real-time communication between browsers and devices. The github repository and documentation for socket.io is here. The canonical example of a socket.io application is a chat application supporting a conversation between clients.

socket.io supports various transports including:

  • web socket
  • html file
  • xhr-polling
  • jsonp – polling

By default, the transports are used in that priority and socket.io automatically degrades a connection when the transport is not supported. Web sockets are not supported by IIS so, as mentioned earlier, a worker role must be used if web socket support is desired for a socket.io application hosted in Windows Azure. Similarly, IE9 does not support web sockets so IE9 use again leads to a degraded connection. (Hint: the Chrome browser provides a better development experience since it does not suffer any connection degradation delay.)

socket.io implements the Node.js EventEmitter interface and so provides a nice demonstration of idiomatic Node.js. The EventEmitter interface comprises:

  • emitter.addListener(event, listener)
  • emitter.on(event, listener)
  • emitter.once(event, listener)
  • emitter.removeListener(event, listener)
  • emitter.removeAllListeners([event])
  • emitter.setMaxListeners(n)
  • emitter.listeners(event)
  • emitter.emit(event, [arg1], [arg2], [...])
  • Event: ‘newListener’

This interface supports the association of named events (or messages) with callbacks. Specifically, emitter.emit() sends a named event while emitter.on() listens for a named event and associates a callback with it. A socket.io application is created by the mutual exchange of named events between the client and the server.

A core sockets object manages connections. It handles a connection event by creating a socket object and passing that to the callback associated with the connection event. The socket object handles individual connections and listens for the disconnect event.  It also supports named events that contain the conversation messages providing the application functionality.

Simple Windows Azure Application using socket.io

A very basic socket.io application hosted in the Windows Azure development environment can be created as follows:

  • Start the Windows Azure PowerShell for Node.js console (using Run as Administrator)
  • cd to some directory
  • Type New-AzureService chat
  • Type Add-AzureNodeWorkerRole
  • cd WorkerRole1
  • Type npm install socket.io
  • Open server.js in some editor (e.g., Sublime Text 2) and replace the contents with the following:

// Import various modules and start listening for socket.io connections
var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs');

// Configure the port to run in the Windows Azure emulator
var port = process.env.port || 81;

// start listening for HTTP connections
app.listen(port);
 
// The handler function returns index.html to the browser
function handler (req, res) {
  fs.readFile(__dirname + '/index.html',  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }
    res.writeHead(200);
    res.end(data);
  });
}

// Handle 'connection' events
io.sockets.on('connection', function (socket) {
  socket.emit('fromServer', { message: 'Connected' });

  socket.on('message', function (data) {
    socket.emit('message', { message: 'Message forwarded' });
    socket.broadcast.emit('message', { message: data.message });
  });
});

  • Create a file named index.html (in the same directory) and copy the following into it:

<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script src="
http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"></script>
<script>
var socket = io.connect('
http://localhost:81');

socket.on('fromServer', function (data) {
    displayMessage(data.message);
});

socket.on('message', function (data) {
    displayMessage(data.message);
});

function sendMessage()
{
    socket.emit('message', { message: $('#MessageText').val() });
};

function displayMessage( message ) {
    $('#Output').text(message);   
};
</script>
<head>
<body>
Message:<input id="MessageText" type="text"/>&nbsp;
<input type="button" value="Send message" onclick="sendMessage();"/>
<div id="Output"/>
<br/>
</body>
</html>

io.sockets.on('connection', function (socket) {
  socket.emit('fromServer', { message: 'Connected' });

  socket.on('message', function (data) {
    socket.emit('message', { message: 'Message forwarded' });
    socket.broadcast.emit('message', { message: data.message });
  });
});

  • Type Start-AzureEmulator –launch

Start multiple browser windows pointing to http://localhost:81.

The UI is simple – with a message box, a Send message button and a status line below. After a few seconds, the status line should display Connected. When a message is typed in one of the message boxes and submitted, the status line in the current windows displays “Message forwarded” while the status line in the other windows displays the message text. Using the appropriate developer tools for the browser it is possible to find out the transport used for communication between the browser and the server.

  • Type Stop-AzureEmulator to shutdown the compute emulator.

This demonstration is very simple with the Node.js server serving up a simple web page to the browsers. The server listens for socket.io connections and on receiving one sends a connected message back to the client and sets up a socket listener for an event named message. On receiving such an event the socket responds by sending an event named fromServer with content Message forwarded back to the client and broadcasts an event named message, containing the message text, to all other clients. On loading, the browser connects to the server and, on connection, adds listeners for two events named fromServer and message. On receiving an event, the response is displayed in the status line. When the button is clicked, socket.emit() is invoked to send the message to the server.

This is a trivial demonstration that shows how easy it is to implement a Node.js application using socket.io inside Windows Azure. Mariano Vazquez uses an equally simple demonstration in a blog post in which he provides additional information about configuring the transport used by the connection.

Posted in Node.js, Windows Azure | Tagged , , , | 3 Comments

MongoDB, Windows Azure (and Node.js)

The Windows Azure ecosystem is being extended both by Microsoft and by third-party providers. This post focuses  on one of these extensions – the MongoDB document database. It shows how MongoDB can be deployed in a Windows Azure hosted service and accessed from other roles in the hosted service using either traditional .NET or the recently released Node.js support.

NoSQL

During the last 30 years SQL databases have become the dominant data storage systems, with commercial offerings such as Oracle, Microsoft SQL Server and IBM DB2 achieving enormous commercial success. These data systems are characterized by their support for ACID semantics – atomicity, consistency, isolation and durability. These properties impose a certainty that is essential for many business processes dealing with valuable data. However, supporting ACID semantics becomes increasingly expensive as the volume of data increases.

The advent of Web 2.0 has led to an increasing interest in long-tail data whose value comes not from the value of a single piece of data but from the magnitude of the aggregate data.  Web logs provide a paradigmatic example of this type of data. Because of the low value of an individual data item this type of data can be managed by data systems which do not need to support full ACID semantics.

Over the last few years a new type of data storage semantics has become fashionable: BASE -basically available, soft state, eventually consistent. While the name may be a bit forced to make the pun, the general idea is that a system adhering to BASE semantics, when implemented as a distributed system, should be able to survive network partitioning of the individual components of the system at the cost of offering a lower level of consistency than available in traditional SQL systems.

In a strongly-consistent system, all reads following a write receive the written data. In an eventually-consistent system, reads immediately following a write are not guaranteed to return the newly written value. However, eventually all writes should return the written value.

NoSQL (not only SQL) is a name used to classify data systems that do not use SQL and which typically implement BASE semantics instead of ACID semantics. NoSQL systems have become very popular and many such systems have been created – most of them distributed in an open source model. Another important feature of NoSQL systems is that, unlike SQL systems, they do not impose a schema on stored entities.

NoSQL systems can be classified by how data is stored as:

  • key-value
  • document

In a key-value store, an entity comprises a primary key and a set of properties with no associated schema so that each entity in a “table” can have a different set of properties. Apache Cassandra is a popular key-value store. A document store provides for the storage of semantically richer entities with an internal structure. MongoDB is a popular document store.

Windows Azure Tables is a key-value NoSQL store provided in the Windows Azure Platform. Unlike other NoSQL stores, it supports strong consistency with no eventually-consistent option. The Windows Azure Storage team recently published a paper describing the implementation of Windows Azure Tables.

10gen, the company which maintains and supports MongoDB, has worked with Microsoft to make MongoDB available on Windows Azure. This provides Windows Azure with a document store NoSQL system to complement the key-value store provided by Windows Azure Tables.

MongoDB

MongoDB is a NoSQL document store in which individual entities are persisted as documents inside a collection hosted by a database. A single MongoDB installation can comprise many databases. MongoDB is schemaless so each document in a collection can have a different schema. Consistency is tunable from eventual consistency to strong consistency.

MongoDB uses memory-mapped files and performance is optimal when all the data and indexes fit in memory. It supports automated sharding allowing databases to scale past the limits of a single server. Data is stored in BSON format which can be thought of as a binary-encoded version of JSON.

High availability is supported in MongoDB through the concept of a replica set comprising one primary member and one or more secondary members, each of which contains a copy of all the data. Writes are performed against the primary member and are then copied asynchronously to the secondary members. A safe write can be invoked that returns only when the write is copied to a specified number of secondary members – thereby allowing the consistency level to be tuned as needed. Reads can be performed against secondary members to improve performance by reducing the load on the primary member.

MongoDB is open-source software maintained and supported by 10gen, the company which originally developed it. 10gen provides downloads for various platforms and versions. 10gen also provides drivers (or APIs) for many languages including C# and F#. MongoDB comes with a JavaScript shell which is useful for performing ad-hoc queries and testing a MongoDB deployment.

Kyle Banker, of 10gen, has written an excellent book called MongoDB in Action. I highly recommend it to anyone interested in MongoDB.

MongoDB on Windows Azure

David Makogon (@dmakogon) worked out how to deploy MongoDB onto worker role instances on Windows Azure. 10gen then worked with him and the Microsoft Interoperability team to develop an officially supported preview release of the MongoDB on Windows Azure wrapper which simplifies the task of deploying a MongoDB replica set onto worker role instances.

The wrapper deploys each member of the replica set to a separate instance of a worker role. The mongod.exe process for MongoDB is started in the OnStart() role entry point for the instance. The data for each member is persisted as a page blob in Windows Azure Blob storage that is mounted as an Azure Drive on the instance.

The MongoDB on Windows Azure wrapper can be downloaded from github. The download comprises two directory trees: ReplicaSets containing the core software as the MongoDBReplicaSet solution; and SampleApplications containing an MVC Movies sample application named MongoDBReplicaSetMvcMovieSample. The directory trees contain a PowerShell script, solutionsetup.ps1, that must be invoked to download the latest MongoDB binaries.

The MongoDBReplicaSetMvcMovieSample solution contains four projects:

  • MongoDBAzureHelper – helper class to retrieve MongoDB configuration
  • MongoDBReplicaSetSample – Windows Azure project
  • MvcMovie – an ASP.NET MVC 3 application
  • ReplicaSetRole – worker role to host the members of a MongoDB replica set.

The MVCMovie project is based on the Intro to ASP.NET MVC 3 sample on asp.net website. It displays movie information retrieved from the MongoDB replica set hosted in the ReplicaSetRole instances. The ReplicaSetRole is launched as 3 medium instances each if which hosts a replica set member. The MongoDBAzureHelper and ReplcaSetRole projects are from the MongoDBReplicaSet solution.

The MongoDBReplicaSetMvcMovieSample solution can be opened in Visual Studio, then built and deployed either to the local compute emulator or a Windows Azure hosted service. The application has two pages: an About page displaying the status of the replica set; and a Movies page allowing movie information to be captured and displayed. It may take a minute or two for the replica set to come fully online and the status to be made available on the About page. When a movie is added to the database via the Movies page, it may occasionally require a refresh for the updated information to become visible on the page. This is because MongoDB is an eventually consistent database and the Movies page may have received data from one of the secondary nodes.

This example provides a general demonstration of how a MongoDB installation with replica sets is added to a Windows Azure project: add the MongoDBAzureHelper and ReplicaSetRole projects from the MongoDBReplicaSet solution and add the appropriate configuration to the ServiceDefinition.csdef and ServiceConfiguration.cscfg files.

The ServiceDefinition.csdef entries for ReplicaSetRole are:

<Endpoints>
    <InternalEndpoint name=”MongodPort” protocol=”tcp” port=”27017″ />
</Endpoints>
<ConfigurationSettings>
    <Setting name=”MongoDBDataDir” />
    <Setting name=”ReplicaSetName” />
    <Setting name=”MongoDBDataDirSize” />
    <Setting name=”MongoDBLogVerbosity” />
</ConfigurationSettings>
<LocalResources>
    <LocalStorage name=”MongoDBLocalDataDir” cleanOnRoleRecycle=”false”
       sizeInMB=”1024″ />
    <LocalStorage name=”MongodLogDir” cleanOnRoleRecycle=”false”
       sizeInMB=”512″ />
</LocalResources>

Port 27017 is the standard port for a MongoDB installation. None of the settings need be changed for the sample project.

The ServiceDefinition.csdef entries for MvcMovie are:

<ConfigurationSettings>
    <Setting name=”ReplicaSetName” />
</ConfigurationSettings>

The ServiceConfiguration.cscfg settings for the ReplicaSetRole are:

<ConfigurationSettings>
      <Setting name=”MongoDBDataDir” value=”UseDevelopmentStorage=true” />
      <Setting name=”ReplicaSetName” value=”rs” />
      <Setting name=”MongoDBDataDirSize” value=”" />
      <Setting name=”MongoDBLogVerbosity” value=”-v” />
      <Setting name=”Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString” value=”UseDevelopmentStorage=true” />
</ConfigurationSettings>

The ServiceConfiguration.cscfg settings for the MvcMovie web role are:

<ConfigurationSettings>
      <Setting name=”ReplicaSetName” value=”rs” />
      <Setting name=”Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString” value=”UseDevelopmentStorage=true” />
</ConfigurationSettings>

It is critical that the value for the ReplicaSetName be the same in both the MvcMovie web role and the ReplicaSets worker role.

The replica set can also be accessed from the MongoDB shell, mongo, once it is running in the compute emulator. This is a useful way to ensure that everything is working since it provides a convenient way of accessing the data and managing the replica set. The application data is stored in the movies collection in the movies database. For example, the rs.stepDown() command can be invoked on the primary member to demote it to a secondary. MongoDB will automatically select one of the secondary members and promote it to primary. Note that in the compute emulator, the 3 replica set members are hosted at port numbers 27017, 27018 and 27019 respectively.

This sample demonstrates the process of adding support for MongoDB to a Windows Azure solution with a web role.

1) Add the following MongoDB projects to the solution;

  • MongoDBAzureHelper
  • ReplicaSetRole

2) Add the MongoDB assemblies to the web role:

  • Mongo.DB.Bson (copy local)
  • Mongo.DB.Driver (copy local)
  • MongoDBAzureHelper  (from the added project)

3) Add the MongoDB settings described earlier to the Windows Azure service configuration.

MongoDB on Windows Azure with Node.js

Node.js is a popular system for developing web servers using JavaScript and an asynchronous programming model. Microsoft recently released the Windows Azure SDK for Node.js which makes it easy to deploy Node.js web applications to Windows Azure.

The SDK provides an extensive set of PowerShell scripts – such as Add-AzureNodeWebRole, Start-AzureEmulator, and Publish-AzureService – which simplify the lifecycle management of developing and deploying a Node.js web application. It contains several introductory tutorials including a Node.js Web Application with Storage on MongoDB. This tutorial shows how to add a replica set implemented, as described earlier, to a web application developed in Node.js.

Summary

The MongoDB on Windows Azure wrapper and the Windows Azure SDK for Node.js tutorial have made it very easy to try MongoDB out in a Windows Azure hosted service.

Posted in MongoDB, Node.js, Windows Azure | Tagged , , , | 2 Comments

Presentation on Windows Azure Brokered Messaging

I did a presentation on Windows Azure Brokered Messaging at the San Francisco Bay Area Azure Developers group – which meets monthly in Microsoft San Francisco. The presentation was based on a post I did on Brokered Messaging.

The deck can be viewed (or downloaded) on SlideShare.

Posted in Brokered Messaging, Service Bus, Windows Azure | Tagged , , , | Leave a comment

First Comes the Writing

… and then comes the marketing.

When Packt Publishing first approached me about writing a book, I headed to Borders to look at a few books it published. I was impressed by the quality of the books, and signed up to write the Microsoft Windows Azure Development Cookbook. Packt has published a number of cloud-related books, and currently is offering an early release version of a book by David Burela (@DavidBurela) titled Microsoft Silverlight 4 and Windows Azure Enterprise Integration. Anyway, Borders no longer exists – but my book does.

Packt is offering a giveaway, through the end of October, in which it will give an eBook version of the Microsoft Windows Azure Development Cookbook to two people who visit the webpage for the book and leave a comment on this post with the one feature that makes them want to read the book. To participate in the giveaway, leave a comment and an email address. When November comes, Packt will give the eBook to two people chosen at random from the commenters.

Note that the chapter on Managing Hosted Services with the Service Management API can be downloaded for free.

Posted in Windows Azure | Tagged , | 2 Comments

On Not Using owner With the Azure AppFabric Service Bus

The Windows Azure AppFabric Service Bus team has been good about providing sample code for the various features it develops. There are also a fair number of blog posts (and books) showing how to use these features. Pretty much all the sample code authenticates operations on the Service Bus via a service identity/password combination where the service identity takes the special value of owner.

In this post, I am going to show how to create and configure a service identity other than owner, and specifically how to ensure that this service identity is less privileged than owner. The intent is to show that, notwithstanding the lack of examples, it is pretty easy to use an alternate service identity. As of mid-September, the Service Bus support ACS v2 – and that is what the material in this post was tested with.

Service Bus Namespace

The starting point for all work with the Service Bus is the service namespace which is created and configured on the Windows Azure Portal. In creating a namespace, a unique name must be provided as well as the location of the Windows Azure datacenter which will host the service endpoints for the namespace. The namespace name becomes the first part of the URI used for these service endpoints. For example, if the namespace name is gress then the service gateway for the gress namespace becomes:

https://gress.servicebus.windows.net/

The various services supported by the Service Bus – including relayed and brokered messaging – are hosted at service paths under the service gateway:

https://{namespace}.servicebus.windows.net/{path}

For example, the following are valid service paths:

https://gress.servicebus.windows.net/topics/interestingtopic

https://gress.servicebus.windows.net/boringtopic/subscriptions/somesubscription

https://gress.servicebus.windows.net/EchoService/

Note that a service path must be specifically associated with a service for the path to have any meaning with regard to a service. For example, although the first service path above probably specifies a topic named topic/interestingtopic there is nothing to prevent it being used instead for a relayed service. The second probably specifies a subscription named somesubscription on a topic named boringtopic. The third likely specifies a relayed service named EchoService.

The paths for a namespace nominally form an infinite tree with the / indicating a branch point. For example, the following shows a namespace with two branches, one for services and the other for topics:

  • https://gress.servicebus.windows.net/services/EchoService
  • https://gress.servicebus.windows.net/services/OneWayService
  • https://gress.servicebus.windows.net/topics/interesting
  • https://gress.servicebus.windows.net/topics/boring

Service Bus Claims

The Service Bus uses the Windows Azure Access Control Service (ACS) for authentication and authorization. The ACS is a Security Token Service (STS) existing as part of claims-based infrastructure. Although it supports limited identity provider (IdP) capability, the primary function of the ACS is in transforming claims in support of federated identity.

This post assumes and requires only minimal understanding of claims-based authentication. The Microsoft Patterns and Practices Team has recently published the second edition of its excellent Guide to Claims-Based Identity and Access Control. This is a good resource for a much deeper understanding of the topic.

When a Service Bus namespace is created, it is associated with a default service identity named owner and a base64-encoded key. This service identity has absolute control of the namespace, including all service paths in it, so it is essential that the associated key be kept secure. This is made even more important by the fact that it is not possible to change the key on the Windows Azure Portal. The default service identity and key can be used to authenticate Service Bus API requests against services hosted by the namespace.

The Service Bus supports three claims which authorize specific operations on a service path. These claims are all of type net.windows.servicebus.action with values:

  • Listen
  • Manage
  • Send

The different values authorize the obvious sets of operations on service paths. For example, the Send claim is required to perform the following operations:

  • Send messages to a listener at a service namespace (relay)
  • Get the queue description
  • Send into to the queue
  • Get the topic description
  • Send to the topic

The complete list of operations and associated authorization requirements is provided in the MSDN documentation, which provides an official take on the material in this post.

When the default service identity, owner, authenticates against the ACS a rule is invoked that assigns all three claims to owner thereby authorizing it to perform any operation on any service path in the namespace.  Note that this discussion elides a lot of claims-based identity plumbing that is, in practice, hidden from the user of the Service Bus API. Although possible, it is strongly recommended that none of the claims be removed from the authorization provided to owner. Doing so can cause significant problems with the namespace.

It is possible to create another service identity with limited privileges, e.g. without the Manage claim. Indeed, it is possible to create a service identity and associate it with only one of the claims. This allows, for example, a sending service identity to be created with only the Send claim and a listening service identity to be created with only the Listen claim. Doing so allows a sending application to be distributed without the possibility of a service identity with a Manage claim being compromised.

By default, owner has Manage, Send and Listen claims over the infinite path tree of the namespace. It is possible to restrict additional service identities to only part of the service path tree. For example, if a service identity is used only to send messages to a topic there is no need for that service identity to have any claims other than Send on the specific service path associated with the topic. The ACS supports this type of restriction, and evaluates whether a service identity has the required permission for an operation by doing a longest string match on the service path. Essentially, it works its way back along the service path seeking a portion of the path for which the service identity has the needed permission. The service identity is authorized to perform a specific operation only if somewhere on the service path it is configured with the required claim and that permission has not been removed later in the path. This permission inheritance is similar to that on a file system. Note that it can cause problems if owner has permissions removed for a service path.

Best Practices

Suggesting that something is a best practice is probably a fair bit above my pay grade. But here goes with some recommended practices:

  • Do not use owner for an operation that does not require the full privileges and claims of owner.
  • Use a service identity with the minimum set of claims needed for a service path.
  • Associate a service identity with the longest service path possible.

Consider the following two full service paths representing a topic and an associated subscription:

  • https://gress.servicebus.windows.net/topics/interestingtopic
  • https://gress.servicebus.windows.net/topics/interestingtopic/subscriptions/mysubscription

If the topic and subscription are created out of band, distinct service identities can be created to authorize sending messages to the topic and receiving messages from the subscription. The sending service identity can be given the Send claim for the topics/interestingtopic service path. The listening service identity can be given the Listen claim for the topics/interestingtopic/subscriptions/mysubscription service path. Separating the privileges like this minimizes the possible damage from a compromised service identity.

SBAzTool

Using an alternative service identity is a little bit more complicated than using owner. However, the Window Azure Service Bus team has provided a command-line utility, SBAzTool, that makes it very easy to add service identities and associate them with service paths.

The SBAzTool is one of the samples provided with the Windows Azure AppFabric SDK v1.5 (September 2011). It is in the ServiceBus/ExploringFeatures/Authorization/ManagingAccessControl directory of the samples. The source code is also supplied in case you want to roll your own service management utility.

The following commands create two new service identities, topicSender and subscriptionListener, and grants the topicSender the Send claim on the topic (from the previous section) and the subscriptionListener the Listen claim on the associated subscription.

sbaztool -n gress -k xkx…6o= storeoptions

sbaztool makeid topicSender
sbaztool grant Send /topics/interestingtopic topicSender

sbaztool makeid subscriptionListener
sbaztool grant Listen /topics/interestingtopic/subscriptions/mysubscription subscriptionListener

sbaztool clearoptions

The storeoptions option is used to store the namespace and the owner key in isolated storage for the SVAzTool – and the clearoptions option removes the information from isolated storage. The SBAzTool can also be used to delete service identities and revoke permissions, as well as display information about service identities and service paths.

SBAzTool makes it really easy to configure service identities and service paths so that service identities other than owner can be used. Consequently, there is no real excuse for not doing so.

Having done all this, we can replace the following code:

TokenProvider tokenProvider =
   TokenProvider.CreateSharedSecretTokenProvider(“owner”, ownerKey);

with

TokenProvider tokenProvider =
   TokenProvider.CreateSharedSecretTokenProvider(“topicSender”, topicSenderKey);

Windows Azure Portal – Access Control Service

The configuration performed by SBAzTool can also be performed manually on the ACS section of the Windows Azure Portal. The UI for ACS configuration on the portal may appear overkill in terms of what has been discussed so far. However, ACS has a much broader use than authorization on the Service Bus.

Clemens Vasters recently made a video of a presentation in which he steps carefully through the process of configuring an issuer and service path. Consequently, I will not repeat the steps here, and will merely put the configuration performed by SBAzTool into the context of the portal.

The makeid option with SBAzTool creates a Service Identity (visible on the portal) that can be authenticated with either a symmetric key or a password. Clemens suggests that the values of these should be the same, and that is what SBAzTool does.

The grant option with SBAzTool creates a Relying Party Application (visible on the portal) for the full service path, e.g.

http://gress.servicebus.windows.net/topics/interestingtopic

Note that the full service path is normalized to specify http rather than any other protocol. Additionally, the tool specifies a token format of SWT and sets the token lifetime to 1200s.

The tool also creates a Service Group (visible on the portal) and associates it with the relying party application configuration for the service path. It also associates the service group with each intermediate service path en route to the service path. This service group generates the appropriate Manage, Send and Listen claims configured by the grant (and revoke) option of SBAzTool. The tool also adds a default service group which generates the Manage, Send and Listen claims for owner on the service path and each intermediate service path. This is to prevent owner not having full rights on the namespace.

Note that currently there is a bug in the portal which causes a problem when following the instructions in the video. Specifically, when creating a relying party application on the portal it is not possible to save the configuration without generating a token signing key. However, doing so causes an error when accessing the service path from an application. The workaround is to go the Certificates and keys section of the ACS configuration on the portal and delete the created token-signing certificate. Everything works fine once that is done.

Summary

My intent in this post was not to give a deep explanation of how to use a claims-based identity framework to secure the Service Bus. Rather, my intent was to provide the minimum amount of information allowing the reader to replace the use of owner with that of a less-privileged service identity. Specifically, I wanted to show how easy it is to do so using the SBAzTool.

Posted in ACS, Azure AppFabric, Service Bus, Windows Azure | Tagged , , , | 1 Comment

Windows Azure AppFabric Applications Presentation at SVCC

I did a presentation on Windows Azure AppFabric Applications  CTP1 at the Silicon Valley Code Camp yesterday. This was based on the post I did several months ago. I uploaded the deck to SlideShare for the benefit of those who were there.

During the talk, I pointed people in the direction of a number of posts on Windows Azure AppFabric Applications by Alan Smith (@alansmith):

  • Introduction to AppFabric Applications.
  • Create Custom External Service in Azure AppFabric June CTP.

The Windows Azure AppFabric Applications CTP can be accessed on the Windows Azure AppFabrics Labs portal. The MSDN documentation is here.

Posted in Azure AppFabric, Windows Azure | Tagged , | Leave a comment

Handling Transient Connection Failures in SQL Azure

This post is one of the recipes in my book Microsoft Windows Azure Development Cookbook. The recipe describes how to use the Transient Fault Handling Framework to handle transient connection failures when using SQL Azure.

The Windows Azure Customer Advisory Team, which supports the framework, describes it as follows:

The Transient Fault Handling Framework solution provides a reusable framework for building extensible retry policies capable of handling different types of transient conditions in applications leveraging SQL Azure, Windows Azure storage (queues, blobs, tables), Windows Azure AppFabric Service Bus and Windows Azure AppFabric Caching Service.

Although the post is specifically concerned with SQL Azure, the general idea can be implemented when using the Windows Azure Storage service, the Windows Azure AppFabric Service Bus and the Windows Azure AppFabric Caching Service.

I highly recommend the Windows Azure Customer Advisory Team blog. It has many posts showing real-world best practices for using the various features of the Windows Azure Platform.

Handling connection failures to SQL Azure

SQL Azure database is a distributed system in which each physical server hosts many databases. This sharing of resources leads to capacity constraints on operational throughput. SQL Azure handles these capacity constraints by throttling operations and closing connections that are using too many resources. SQL Azure also closes connections when it alleviates operational hot spots by switching from a primary SQL Azure database to one of its two backup copies. Furthermore, connectivity to a SQL Azure database is likely to be less reliable than connectivity to a Microsoft SQL Server database on a corporate LAN. It is imperative therefore that applications using SQL Azure be designed to withstand the connection failures that are far more likely to occur than with Microsoft SQL Server.

One of the mantras of cloud development is design for failure. It is important that applications using SQL Azure be designed to handle failures appropriately. There are two kinds of error: permanent errors indicating a general failure of part of the system and transient errors existing only for a brief time. Permanent errors perhaps indicate a logical problem with the application—and handling them may require code changes. However, an application should handle transient errors gracefully by retrying the operation that led to the error in the hope that it does not recur. A dropped connection should be regarded as transient, and an application should respond to a dropped connection by opening a new connection and retrying the operation.

There remains the problem of distinguishing permanent from transient errors. This can be done by comparing the error returned from a failed operation with a known list of transient errors. An application can therefore include a retry mechanism that checks the status of operations and retries any operations that experienced a transient error.

The Windows Azure AppFabric Customer Advisory Team has made available on the MSDN Code Gallery the source code and pre-compiled assemblies for the Transient Fault Handling Framework for Azure Storage, Service Bus, and SQL Azure. This comprises a set of classes that can be used to detect transient failures and retry SQL operations. It contains an extensible way to identify transient failures, with various examples including one that compares an error with a list of known transient failures. The Transient Fault Handling Framework provides various built-in retry backoff techniques that specify how often and frequently an operation should be retried following a transient failure. These include both a fixed interval and an exponential delay between retries. The classes in the Transient Fault Handling Framework include various extension methods that simplify the use of the framework, thereby minimizing the work required to add the handling of dropped connections and other transient failures to an application using SQL Azure.

In this recipe, we will learn how to use the Transient Fault Handling Framework for Azure Storage, Service Bus, and SQL Azure to handle dropped connections and other transient failures when using SQL Azure.

Getting ready

The recipe uses the Transient Fault Handling Framework for Azure Storage, Service Bus, and SQL Azure. It can be downloaded from the following URL:

http://code.msdn.microsoft.com/Transient-Fault-Handling-b209151f 

This download is a Visual Studio solution with precompiled output assemblies that are referenced in the project used in the recipe.

How to do it…

We are going to connect to SQL Azure using ADO.NET and perform various DDL and DML operations taking advantage of the transient-error handling provided by the Transient Fault Handling library. We do this as follows:

1. On the Project Properties dialog in Visual Studio, set the Target Framework to .NET Framework 4.

2. Add the following assembly references to the project:

Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.dll
System.configuration.dll

3. Add a new class named RetryConnectionExample to the project.

4. Add the following using statements to the top of the class file:

using System.Data;
using System.Data.SqlClient;
using Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling;
using Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.SqlAzure;
using Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.Configuration;

5. Add the following private members to the class:

String connectionString;
RetryPolicy connectionRetryPolicy;
RetryPolicy commandRetryPolicy;

6. Add the following constructor to the class:

public RetryConnectionExample(String server, String database,
   String login, String password)
{
   SqlConnectionStringBuilder connStringBuilder;
   connStringBuilder = new SqlConnectionStringBuilder();
   connStringBuilder.DataSource = String.Format(“{0}.database.windows.net”, server);
   connStringBuilder.InitialCatalog = database;
   connStringBuilder.Encrypt = true;
   connStringBuilder.TrustServerCertificate = false;
   connStringBuilder.UserID = String.Format(“{0}@{1}”, login, server);
   connStringBuilder.Password = password;
   connectionString = connStringBuilder.ToString();

   connectionRetryPolicy = new RetryPolicy<SqlAzureTransientErrorDetectionStrategy>(
      5, TimeSpan.FromMilliseconds(100));

   connectionRetryPolicy.RetryOccurred += RetryConnectionCallback;

   RetryPolicyConfigurationSettings retryPolicySettings =
      ApplicationConfiguration.Current.GetConfigurationSection<
         RetryPolicyConfigurationSettings>(RetryPolicyConfigurationSettings.SectionName);

   RetryPolicyInfo retryPolicyInfo = retryPolicySettings.Policies.Get(“FixedIntervalDefault”);
   commandRetryPolicy =
      retryPolicyInfo.CreatePolicy<SqlAzureTransientErrorDetectionStrategy>();
   commandRetryPolicy.RetryOccurred += RetryCallbackCommand;
}

7. Add the following callback methods to the class:

private void RetryConnectionCallback(
   Int32 currentRetryCount, Exception lastException, TimeSpan delay)
{
   Int32 retryCount = currentRetryCount;
}

private void RetryCallbackCommand(
  Int32 currentRetryCount, Exception lastException, TimeSpan delay)
{
   Int32 retryCount = currentRetryCount;
}

8. Add the following method, retrieving the session tracing Id, to the class:

public String GetSessionTracingId()
{
  String commandText = “SELECT CONVERT(NVARCHAR(36), CONTEXT_INFO())”;

  String sessionTracingId;

  using (ReliableSqlConnection connection = new ReliableSqlConnection(connectionString))
 
{
     connection.Open();
     using (SqlCommand sqlCommand = connection.CreateCommand())
    
{
       
sqlCommand.CommandText = commandText;
       
sessionTracingId = sqlCommand.ExecuteScalarWithRetry() as String;
     }
   }  

   return sessionTracingId;
}

9. Add the following method, creating the Writer table, to the class:

public void CreateTable()
{
  String commandText = @”CREATE TABLE Writer (
    
Id int PRIMARY KEY NOT NULL,
    
Name nvarchar(20) NOT NULL,
    
CountBooks int NULL)”;

  using (ReliableSqlConnection connection =
    new ReliableSqlConnection(connectionString, connectionRetryPolicy))
  {
    
connection.Open();

     using (SqlCommand sqlCommand = connection.CreateCommand())
    
{
      
sqlCommand.CommandText = commandText;
      
sqlCommand.ExecuteNonQueryWithRetry();
    
}
   }
}

10. Add the following method, dropping the Writer table, to the class:

public void DropTable()
{
   String commandText = “DROP TABLE Writer”;

   using (ReliableSqlConnection connection = new ReliableSqlConnection(connectionString))
  
{
     
connection.Open(connectionRetryPolicy);

      using (SqlCommand sqlCommand = connection.CreateCommand())
     
{
        
sqlCommand.CommandText = commandText;
        
sqlCommand.ExecuteNonQueryWithRetry(commandRetryPolicy);
      }
   }
}

11. Add the following method, querying the Writer table, to the class:

public void QueryTable()
{
   String commandText = “SELECT * FROM Writer”;

   using (ReliableSqlConnection connection =
      new ReliableSqlConnection(connectionString, connectionRetryPolicy, commandRetryPolicy))
   {
      connection.Open();

      using (SqlCommand sqlCommand = new SqlCommand(commandText, connection.Current))
     
{
         using (IDataReader reader = connection.ExecuteCommand<IDataReader>(sqlCommand))
        
{
            Int32 idColumn = reader.GetOrdinal(“Id”);
           
Int32 nameColumn = reader.GetOrdinal(“Name”);
           
Int32 countBooksColumn = reader.GetOrdinal(“CountBooks”);
           
while (reader.Read())
           
{
              
Int32 id = (Int32)reader[idColumn];
              
String name = reader[nameColumn] as String;
              
Int32? countBooks = reader[countBooksColumn] as Int32?;
           
}
         }
      }
   }
}

12. Add the following method, inserting rows in the Writer table, to the class:

public Int32 InsertRows()
{
   String commandText = @”INSERT INTO Writer (Id, Name, CountBooks)
     VALUES
        (1, N’Cervantes’, 2),
       
(2, N’Smollett’, null),
       
(3, ‘Beyle’, 4)”;

   Int32 rowsAffected;
  
using (SqlConnection connection = new SqlConnection(connectionString))
  
{
     
connection.OpenWithRetry();

      using (SqlCommand sqlCommand = new SqlCommand(commandText, connection))
     
{
         rowsAffected = sqlCommand.ExecuteNonQueryWithRetry();
     
}
   }

   return rowsAffected;
}

13. Add the following method, updating a row in the Writer table, to the class:

public Int32 UpdateRow()
{
   RetryPolicy exponentialRetryPolicy = RetryPolicy.DefaultExponential;

   String commandText = @”UPDATE Writer
     
SET Name=@Name
     
WHERE Id=3″;

   Int32 rowsAffected;
  
using (SqlConnection connection = new SqlConnection(connectionString))
  
{
     
connection.OpenWithRetry(exponentialRetryPolicy);

      using (SqlCommand sqlCommand = new SqlCommand(commandText, connection))
     
{
        
SqlParameter sqlParameter = new SqlParameter()
        
{
           
ParameterName = “@Name”,
           
Value = “Stendhal”,
           
SqlDbType = SqlDbType.NVarChar,
           
Size = 20
        
};

         sqlCommand.Parameters.Add(sqlParameter);

         rowsAffected = sqlCommand.ExecuteNonQueryWithRetry(exponentialRetryPolicy);
     
}
   }
   return rowsAffected;
}

14. Add the following method, using the methods added earlier, to the class:

public static void UseRetryConnectionExample()
{
   String server = “SERVER_NAME”;
  
String database = “DATABASE_NAME”;
  
String login = “LOGIN”;
  
String password = “PASSWORD”;

   RetryConnectionExample example = new RetryConnectionExample(
      server, database, login, password);
  
example.GetSessionTracingId();
   example.CreateTable();
   example.InsertRows();
   example.QueryTable();
   example.UpdateRow();
   example.QueryTable();
   example.DropTable();
}

15. Add the following Transient Fault Handling Framework configuration to the app.config file for the project:

<configSections>
   <section name=”RetryPolicyConfiguration”
type=”Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling.Configuration.RetryPolicyConfigurationSettings,
Microsoft.AppFabricCAT.Samples.Azure.TransientFaultHandling”/>
</configSections>

<RetryPolicyConfiguration defaultPolicy=”FixedIntervalDefault”>
   <add name=”FixedIntervalDefault” maxRetryCount=”10″ retryInterval=”100″/>
</RetryPolicyConfiguration>

How it works…

In Step 1, we modify the output target of the project to make it consistent with the requirements of the Transient Fault Handling Framework. In Step 2, we add references to the Transient Fault Handling Framework assembly and to the System.configuration assembly used to access the Transient Fault Handling configuration in the app.config file.

In Steps 3 and 4, we set up the class. In Step 5, we add private members for the connection string and two RetryPolicy instances. In the constructor, we add in Step 6, we initialize the connection string using a SqlConnectionStringBuilder instance. Configuring a connection string for SQL Azure is precisely the same as for Microsoft SQL Server apart from the way in which the DataSource is specified—with the fully qualified host name. We turn encryption on, as this is required, and set TrustServerCertificate to false, so that the server certificate is validated. Instead of building the connection string like this, we could have loaded it from a configuration file.

For demonstration purposes, we initialize the RetryPolicy private members using different techniques. We create the connectionRetryPolicy member directly by providing initialization values in its constructor. We associate the RetryOccurred callback method with the connectionRetryPolicy member. We create the commandRetryPolicy member by retrieving a FixedIntervalDefault policy from the app.config file. We associate the RetryOccurred callback method with the commandRetryPolicy member. In both cases, we use SqlAzureTransientErrorDetectionStrategy to identify transient errors. This compares an error with a list of pre-defined transient errors.

In Step 7, we add two RetryOccurred callback methods the class. These have a trivial implementation that in a real application could be replaced by logging that a retry had occurred.

In Step 8, we create and open a ReliableSqlConnection which we use to create a SqlCommand. The connection is closed automatically when we exit the using block. We use SqlCommand to retrieve the session tracing ID for the connection. This is a GUID, identifying a particular connection, which can be provided to SQL Azure Support when its help is sought in debugging a problem. We use the default RetryPolicy when we open the connection and when we invoke the ExecuteScalarWithRetry() extension method. Note that the default RetryPolicy identifies all errors as being transient.

In Step 9, we invoke a CREATE TABLE operation on SQL Azure to create a table named Writer. The table has three columns: the Primary Key is the Id column; the remaining columns store the name of a writer and the number of books they wrote. We use the connectionRetryPolicy, configured in the constructor, when the connection is opened and the default RetryPolicy when we invoke the ExecuteNonQueryWithRetry() extension method.

In Step 10, we invoke a DROP TABLE operation on SQL Azure to drop the Writer table. We use the default RetryPolicy when the connection is opened and the commandRetryPolicy when we invoke the ExecuteNonQueryWithRetry() extension method.

In Step 11, we retrieve all rows from the Writer table and then iterate over them to examine the content of each column. We use the connectionRetryPolicy when the connection is opened and the commandRetryPolicy when we invoke the ExecuteComman<IDataReader>() extension method.

We insert three rows in the Writer table in Step 12. We invoke the OpenWithRetry() and ExecuteNonQueryWithRetry() extension methods to use the default RetryPolicy when we open and use the connection respectively. In Step 13, we use the same extension methods when we update a row in the Writer table. In this case, however, we parameterize them, so that we use the DefaultExponential retry policy when we open and use the connection. This default policy identifies all errors as transient.

In Step 14, we add a method that invokes the methods added earlier. We need to provide the server name, the database name, the login, and the password.

In Step 15, we add the configuration used to configure a RetryPolicy instance in Step 6. In doing so, we need to add a configSection element specifying the assembly used to access the configuration and then we add a RetryPolicyConfiguration element in which we specify a configuration we name FixedIntervalDefault.

Note that, with an appropriately configured connection string, all the code in this recipe can be run against Microsoft SQL Server—with the exception of the retrieval of the session tracing ID in Step 8.

There’s more…

The Transient Fault Handling Framework for Azure Storage, Service Bus, and SQL Azure can also be used for retrying operations against the Windows Azure Storage Service and the Windows Azure Service Bus.

See also

Valery Mizonov (@TheCATerminator) of the Windows Azure AppFabric Customer Advisory Team has written a blog post on Best practices for handling transient conditions in SQL Azure client applications. He explains how to use the Transient Fault Handling Framework. The post is available at the following URL:

http://windowsazurecat.com/2010/10/best-practices-for-handling-transient-conditions-in-sql-azure-client-applications/

Posted in Azure AppFabric, Service Bus, SQL Azure, Storage Service, Windows Azure | Tagged , , | 2 Comments