BestASPNETHostingReview.com | Best and reliable ASP.NET State server. I recently ran into an issue with the ASP.NET SessionState. It isn’t a fault of the SessionState itself, but likely an issue with my configuration or uses. Essentially the state was being reset too often. Although I had a timeout value of 1440 minutes, users were getting kicked out after 10-15 minutes. I eventually found out that (for some reason) the IIS worker process was being reset (although it wasn’t configured to self-reset), probably due to an unrecoverable error in some of our legacy-based code. And since our SessionState was set to InProc, all of the session data was stored in-the-process and was thus lost whenever it died.
I started researching the alternatives and discovered the proper way to configure the StateServer that comes with ASP.NET to move your sessions out-of-process. This way, you can literally reset IIS (or if the StateServer is on another machine, reboot your IIS server machine) without losing session. This seemed like a very appealing situation, and one that many people online endorse as best practice.
Another benefit of moving the SessionState out-of-process is that you set yourself up nicely for eventually moving to multiple web servers, or even running simultaneous multiple instances of your application pools on the same machine to boost performance.
The only downside (and yes, there’s always a catch) is that out-of-process state does not give as good performance as InProc does. However, from my initial testing, I haven’t found any significant, noticeable difference after the session is initialized. Another catch, which I’ll discuss later, is that all data that goes into an out-of-process session must be serializable and flagged as such with the SerializableAttribute.
Let’s start from the top. The SessionState is a collection of data that is persisted across multiple web requests to ASP.NET. This can be authentication information, a shopping cart, a theme, or whatnot – essentially any information that you want the server to remember for the next time the user “does something” on your site. This can also be accomplished on the page level with ViewState, but that sends more data back and forth between the client and your server.
If you’re using the cookie method of “tagging” your SessionState (which you should, because cookieless is vulnerable to session hijacking), you’ll have a tiny little harmless cookie called ASP.NET_SessionId which contains a unique session ID that looks something like “okeiohntcofecw55svocxwiz”. This ID is sent to the web server to let the server know which session to retrieve.
If the SessionState is running InProc, all ASP.NET has to do is look at the memory it has of that session information and retrieve or set the values required. However, if that process gets reset (due to an IIS reset, power outage, reboot, failed process, etc) then it no longer has a record of that session information, so that SessionId is no longer valid and the user is “kicked off”.
Additionally, if you increase the number of worker processes per application pool, thinking you’ll be getting better performance on a multiprocessor server, you’ll find that the users continually get kicked off, because each process doesn’t know about the session state of the other so they continually reset the session on each other. This is the same problem you’ll encounter if you try to move to two load-balanced web servers.
The StateServer Solution
Included with .NET is a Windows service called the ASP.NET State Service. This is disabled by default, so if you’re reading this far you may not know about it. This service runs as an additional process so that if the IIS worker process gets reset, the state service is still running with all the session information.
You can even run this State Service on another Windows Server machine. This way, you can have one machine managing your session state, while you can have one or more web servers handling requests. An example situation might look something like this:
Even though that might be what a more advanced operation might look like, you will likely (such as in development or for a small-load web server) run the StateServer on the same machine as IIS.
Keep in mind that the SessionState is still being stored in memory with the StateServer solution… there’s no persisting of the state to disk. So if the StateServer process gets restarted or rebooted, so does your session information.
The SQL Server Solution
Another solution supported natively by ASP.NET is to use SQL Server to persist state information to disk. This way, even the server handling your state can be rebooted without losing session. This may be the preferred way of doing things for very high-end operations or situations where you need to maintain that information for security or contractual purposes. However, I will not be discussing that here, because I haven’t tried it myself. There’s many resources to learn about this on the web, such as this article from Microsoft.
To enable the ASP.NET State Service, all you have to do is configure the service on both your development and production machines.
- Click Start / Run or type Win + R.
- Type in services.msc and press Enter or click OK.
- Locate the ASP.NET State Service in the Services (local) list.
- Right click on it and choose Properties.
- Change the Startup Type to Automatic so that it starts on boot.
- Click the Start button to get it started now.
- Click OK to close the dialog.
Now, if you pull up Task Manager, you’ll notice a nice little aspnet_state.exe process running in addition to the IIS worker process (w3wp.exe). This process is the new StateServer that will maintain all your state data. But in order to use it, we must enable your ASP.NET web site to use the out-of-process StateServer.
Modifying your Web.Config
For the site that you’d like to have use the out-of-process StateServer, first open your web.config file for that site.
Locate (or add) a sessionState element in the system.web section of the config file, like this:
Note the cookieless=”UseCookies” and mode=”StateServer” attributes. These are required to use the StateServer in a cookie’d fashion.
The timeout attribute is the time, in minutes, that you want the session to remain valid.
Also note that this example above is for the StateServer running on the same machine as IIS. With no connection string specified, it looks for a StateServer running on the local machine. If you need to move the StateServer onto another machine, you must match up your MachineKeys and set a StateServer connection string for IIS to connect to. Google is your friend.
Now, your site should be using the StateServer for all of its session data. You may (or may not, but it might be a good idea) need to restart IIS for this to be optimally configured.
Non-Serializable Session Data
The only caveat in this post, and it’s a big one, is that you will receive an error if you try to store non-Serializable data into the session now that you have an out-of-process state (i.e. a System.Data.DataView). Serializable classes are those that have the Serializable attribute set and are optimized for serialization (i.e. a System.Data.DataTable).
You will need to review and test your code (or write new code accordingly) to make sure that you are not storing non-Serializable data to your session when using out-of-process state. If you are using custom classes to store session data, review them for serializable members and properties, and then mark them as serializable.
I’ve seen developers proclaim online that all ASP.NET devs should design their applications around an out-of-process session model, and now that I’ve discovered it, I am inclined to agree. If you design from the beginning to be compatible with a StateServer or SQL database state server, you can easily make the jump from one web server to two.
A few things to think about are the amount of memory available to the state service, latency and the connection between servers if the StateService is running on another machine, and how to minimize state since it’s now being transferred between processes.
What are your experiences with out-of-process state, and do you have any advice for others?