Wednesday, April 18, 2007

Session Management in ASP.NET

ASP.NET Session State: Architectural and Performance Considerations

I recently came across a great post on one of the internal forums describing the strengths and weaknesses of different ASP.NET session state strategies. Its author, J.D. Meier, has graciously given me permission to use it as the basis of a blog entry.

As you're probably aware, state management is an important consideration for web developers. The HTTP protocol is connectionless, so any web application that persists data across multiple web page requests needs some mechanism to ensure this session-based data is maintained. Examples of session-based data include shopping carts (on an ecommerce site), the currently logged-on user credentials, and other application-specific data that would normally be held on a client. Various strategies have been utilised over the last few years, including hidden forms, cookies and server-based state engines. Of these choices, the latter is perhaps architecturally most attractive since it reduces the dependence on a client; unfortunately, maintaining session state on the server can be expensive on resources and makes it hard to scale out using web farms or secure pages with HTTPS.

Enter the ASP.NET session state engine, which attempts to make server-side session state a much more viable option. ASP.NET offers three separate choices for session state storage when it's switched on: locally on the server (InProc), remotely in a SQL Server database (SqlServer), or remotely using a session state service (StateServer). I'll go through each of those options and compare the benefits of each.

InProc

The local option is not dissimilar to that provided by ASP, in that it requires all requests to come to the same physical server rather than being randomly split across multiple IIS machines. The upside is that it's very fast (it runs in-process), and it's simple to implement. If you've just got one web server, this is the best choice in most scenarios. The only time when you might want to consider something else in this scenario is when the session data is expensive to rebuild, since any InProc session data is flushed when the ASP.NET worker process or IIS restarts. If, for example, you're maintaining a shopping cart as local session data that gets cleared out, you risk annoying customers sufficiently that they take their business elsewhere.

For multiple servers, InProc is unsuitable unless you can implement some form of server affinity, so that every time a particular client requests a web page they are directed back to that same server. Services such as Network Load Balancing (part of Windows Server 2003 Enterprise Edition) can provide this, although they inevitably add their own overhead.

StateServer

I've come across a few developers who haven't come across this choice. The state server relies on a Windows service which is disabled by default, which perhaps explains why people haven't noticed it - go to Administrative Tools / Services and enable the ASP.NET State Service to get it working. You can run the state service on a dedicated machine or shared with a web server host; the main requirement to make this service work efficiently is plenty of RAM. Because the service is isolated from IIS, you can restart IIS without losing the session data contained within it, and you can point multiple distributed ASP.NET boxes at the same service, thereby removing server affinity issues. However, the session data isn't persisted onto disk, so it can't be backed up and a server reboot will lose the data. On the plus side, you don't need SQL Server or anything beyond a Windows licence to run it, making this option easy to set up and maintain. This option is however signficantly slower than using InProc, due to network latency and roundtrip costs. Keeping the state server on a dedicated private LAN with the other web server boxes will help.

Finally, don't forget that you can run the ASP.NET State Service in a single web server environment - this provides durability against IIS restarts, but at a performance cost due to it running out of process.

SqlServer

This is the high-end option in terms of flexibility and reliability, but is also the most expensive to build and maintain. Rather than storing session data in memory, it is persisted to a SQL Server instance. It's more reliable than any of the other approaches, since the data is persisted in a more durable form (e.g. it will survive a server restart and can be backed up). You can even use SQL Server clustering support to increase session state reliability still further. From a performance point of view, it's generally comparable to the StateServer service when you've got multiple web servers using it for session state. The session state itself is stored as a BLOB in a persisted or temporary table, which can reduce the serialization cost but makes it harder to view the session data itself.

In most cases, integrated Windows authentication is the best choice, preferably utilising Kerberos (NTLM requires an extra roundtrip for authentication). Connection pooling can be used to minimise the initial performance hit.

Happy Programming !!

No comments: