By Jim White (Intertech Instructor and Director of Training)
If you are a Web developer, you are probably very familiar with managing user state – that is you are familiar with tracking user activity and actions across several request-response exchanges that occur in Web applications. Since HTTP is a stateless protocol, developers over the years have developed all sorts of means to manage state. You’ll even find an MSDN page providing alternatives and recommendations for state management here. Cookies, hidden fields, and query strings are some client-side options to tracking user state. When it comes to managing that state on the server-side, most Web developers rely on session objects.
Session Objects in Azure
There are sessions in Azure just as you would find them in ASP.NET applications. For example, the following lines of code would add and retrieve a Customer from the current HttpSessionState object.
Session[“currentCustomer”] = new Customer(“Joe”, “Smith”);
Customer customer = (Customer)Session[“currentCustomer”];
So, the Web server in Azure provides you the same session object you are accustomed to working with today. However, the sessions in Azure are not ‘sticky.’ In other words, if you have multiple Web role instances, Azure does not guarantee to route a user’s requests to the same Web role instance. In fact, the load balancer in Azure works to the opposite effect. The load balancer tries to route traffic evenly to all instances regardless of the request’s origination. Since each Web role instance has its own session, there is effectively no shared session data across Web roles.
To help understand the implications of this issue, say the user represented by the “client” box above is working with a retail Web site. If “Request 1” was a request to add an item to the shopping cart, when the user goes to check out per “Request 2”, she will be very disappointed to find the item missing from her cart. That is because the item is in a shopping cart session object associated to the first Web Role and not the shopping cart object associated to the second Web Role.
In-memory Web Server Session Management
Session objects, when managed by the Web server, are often stored in memory on the Web server. Of course in Windows Azure, each Web role has its own Web server. You could remove this issue by having only one Web role. By having just one Web role, you remove load balancing from the picture. Limiting your application to one Web role also limits your application’s scalability – presumably one of the reasons you chose to move your application to Azure in the first place. If you eventually need to scale your application to involve multiple instances, you now need to rewrite parts of your application.
Even if scalability is not a chief concern, there are other reasons you should hesitate before using standard Web server sessions to manage user state. In-memory sessions use a precious commodity: memory. If your application puts a lot of data in session, your application can experience out of memory errors. Also, if your Web role fails, Azure establishes your instance on another server. However, the in-memory session information – still back on the other Web server – is lost.
Session State in Azure Storage
What’s the solution to this session dilemma? Persist your session objects in Azure Storage versus in-memory on the Web server. Putting session information in table storage has several advantages. It scales. It allows all instances of a Web role (or any role) to share session data. It is always available and stored in triplicate. So, if your role goes down, session data is not lost.
Setup to Use Table Storage for Sessions
To use table storage to persist sessions, you must first modify the Web.config file in your Web role project to indicate you are using a different session provider. Add the following element to the <system.web> element, replacing ‘yourWebAppName’ with the name of your Web application.
<add name=”TableStorageSessionStateProvider” type= “Microsoft.Samples.ServiceHosting.AspProviders.TableStorageSessionStateProvider”
Note: you may find Visual Studio editors provide false warnings on this entry indicating type and applicationName attributes are not allowed.
Secondly, get a copy of the Windows Azure Platform Training Kit (the June 2010 release is available for download here). In the kit, look for an AspProviders Visual Studio project (its in the WindowsAzureDeployment lab under Source\Assets). This project contains a TableStorageSessionStateProvider class that implements the Table Storage Service Provider.
You can either include the AspProviders project into your solution or compile the DLL and reference the DLL. The AspProviders project uses the DataConnectionString configuration setting to get all the information needed to access table storage for your account. Make sure you establish your DataConnectionString and point it to use development storage or your storage in the cloud as appropriate.
Using Sessions Persisted in Table Storage
With these adjustments, you use the same API calls as those listed at the top of this blog entry to add and retrieve data to/from session. However, now user state is not held in memory on the Web server. It is, instead, persisted to table storage. The TableStorageServiceProvider actually creates a ‘Sessions’ table in table storage by default. So you don’t even have to set up or manage the actual table schema in table storage. After you test and run your application, you can use a tool like Cerebrata’s Cloud Storage Studio to explore the “Sessions” data table.
When exploring the Sessions table in table storage, be aware that the data is not stored in a fashion for easy viewing. In fact, the actual session data is packed away in an associated blob storage record. Also, don’t forget that objects must be serializable if they are to be stored in session.