Web farms in .NET and IIS part 5: Session state management

Managing session state is vital in a web farm environment. Many websites simply cannot function without maintaining state throughout the user’s visit. Session variables are maintained by the web server and a cookie is saved to the client. This cookie will inform the server who the user is and the server can then extract the session information from it. You will need to give extra consideration to state management in a web farm scenario.

Imagine that the web request is routed to farm machine A and the code invoked by the request relies on some parameters stored in the session. If the same user is then routed to machine B in the next web request which also relies on the session state then the results may unpredictable: as the value is not available in the session then a null pointer exception may be thrown, or if you put in a guard clause then that variable may be assigned some default value thereby “forgetting” what the value was in the previous web request. And then the wrong default value may be stored in the database instead of the one the user has selected.

In this post we discussed session stickiness which makes sure that the same user is directed to the same machine on subsequent requests. We also said that we should avoid this solution so that the load balancer can pick the “right” machine in the farm based on the actual load. In case you need to deploy a Classic ASP site in a web farm then this is your only option: Classic ASP doesn’t have any built-in session state solution that works with a web farm.

You can define session state handling in IIS. Let’s see what the options are.

Session state management

Every web developer must have used the session state in some form. A classic example is when a user fills in a step-by-step signup questionnaire then the values are store in a session:

Session["FirstName"] = txtFirstName.Text;
Session["LastName"] = txtLastName.Text;

The question is how and where these session states are stored.

In IIS you can open the session state manager by choosing the web site and then clicking the Session State icon:

Session state icon in IIS

This opens the following window:

Session state options in IIS

The default choice is in-process. This means that the session state data is stored inside of the worker process called w3wp.exe. You can think of this as storing the session inside the application pool. This option provides the fastest retrieval of the session state as there’s no need to connect to another computer or database to read or store the session data. However, there are several disadvantages which are also related but not limited to web farms:

  • Session management runs inside the worker process which means that it’s consuming memory in the worker process. This memory could be used by other functionality of your web site.
  • The session state is lost as soon as the application pool of your website in IIS is recycled. It is gone forever.
  • This option is particularly dangerous in a web farm environment. Take the example I mentioned above: one farm machine stores the session state but not the other. Subsequent web requests from the same user may not read the correct session state

This last point forces us to introduce sticky sessions which beats the purpose of load balancing so you should always try to avoid this path.

The points above will certainly lead to bad user experience in the form of inexplicable exceptions, unexpected values and irritating bugs. Each machine in the web farm will store its own little subset of the full session state:

In process session management

Salvation comes in the exact opposite of in-process state management: out-of-process state management. This option simply means that instead of storing the session state within the application pool we store it somewhere else, in a place which is independent of the website:

  • ASP.NET session state service: this provides a somewhat slower service than the in-process variant as we need to make calls to a remote server. All session data is stored in memory so shutting down the state machine will wipe out all session data as well
  • SQL server, where we store the state in a database: this option provides the most reliable service but is also the slowest as all data must be read to and from a database. Session data is not lost even if the state machine is shut down
  • A third party component, possibly commercial or self-built

So we move out the session state from each individual farm machine to one central place where the session can be read and stored:

Out of process state management

ASP.NET state service

Open the Services management window and you should find the following service there:

ASP.NET state service in Services window

So it’s a plain old Windows service. Every machine that has a .NET framework installed has this service. As you see by default it is turned off and is set to a manual start mode. Change this to automatic and start the service to activate it:

Set service to automatic

Normally you would do this on the designated state service machine. This will allow external machines to connect to the state service and put session data in and out of it and it’s all stored in memory. Restarting either the state server or just that Windows service will erase the session data.

Also, the service cannot be accessed remotely by default. To enable that option you need to set the value of the following registry key to 1: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection. Don’t forget to restart the asp.net state service after the registry key change.

So this Windows service is easy to use but there’s a significant disadvantage: the State Server does not provide any failover option. If the service is stopped or the machine running the state service is shut down then your session variables will not be available and cannot be saved. If you are willing to take that risk then you’ll be good to go in a couple of minutes.

SQL server

As mentioned above this provides the most reliable session service but it also the slowest. If you rely on the session state a lot in your code then there will be a lot of read and write operations to and from your SQL server affecting its performance. However, the added redundancy may well compensate for the slight increase in the performance overhead.

You can have a cluster of SQL Servers configured with SQL AlwaysOn so that even if one state machine goes down then the other machine can take over. As state is persisted in database tables it is only lost if the table data is wiped out. Otherwise it is available even if the machine is restarted.

You must prepare your database to fit the session state schema. This can be done using the aspnet_regsql.exe tool which is located in the following folder:

ASP net reg sql tool location

You can only perform the necessary schema change from the command line. If you double-click the executable file then a GUI will open but that GUI is used for setting up ASP.NET membership, profiles and role management tables in the database. It is not meant for state management purposes.

Make sure that the user you provide in the command line arguments has admin rights to the database otherwise the command will fail. The command will need access to msdb system-stored procedures.

The command line arguments include a paramenter called -sstype which stands for the SQL Server session type. It has 3 options: ‘t’ for temporary, ‘p’ for permanent and ‘c’ for custom. T and p create a database called ASPState. T saves the session in the tempdb database so this data is only temporary: session state is lost if SQL Server is restarted. P on the other hand causes the session data to be saved in the ASPState database and allows the session state management to use the same SQL server.

Make sure to open port 1433 on the machine where you’re intending to save the session data. Note that the parameters are case-sensitive. Examples:

aspnet_regsql.exe -ssadd -sstype c -S sql.mycompany.local -d SQLState -U adminUserName -P adminPassword

-ssadd simply means to add SQL Server session state. The server is specified though -S, -d specifies the database, -U the username and -P the password.

aspnet_regsql.exe -ssadd -sstype c -S sql.mycompany.local -d SQLState -E

This is the same as above except that it uses Windows authentication.

aspnet_regsql.exe -ssadd -sstype p -S sql.mycompany.local -E

Here we ask the tool to create the ASPState database, which is the default name of the session state database, hence we don’t need the -d parameter.

You can view all parameters by typing aspnet_regsql.exe /?

Third party tools

The following tools are all reliable session managers that are built for highly available, highly scalable web farms. They either maintain session data in-process and replicate all changes immediately or store the session data out-of-process through a custom worker process that resides on each server.

Preparing your web site

You need to declare in web.config in case you want to use an out of process state management option. Create a new MVC internet application or simply open the one we used in the previous blog post. Open web.config. You need to declare the session management options within the system.web node. Example:

<sessionState mode="StateServer"								stateConnectionString="tcpip=machinename:42424">
</sessionState>

If you want to use the StateServer service on the local machine then you can ignore the stateConnectionString attribute.

Use intellisense to check the attribute options for the session state node. You will find the SQL variant there as well. You’ll probably recognise the purpose of the mode attribute and its value. The state connection string will be the address of the state machine and the port of the ASP.NET session service. By default it is listening on port 42424.

In case you’re opting for the SQL Server type of solution then this section may look like the following:

<sessionState mode="SQLServer" allowCustomSqlDatabase="true"
	sqlConnectionString="the connection string name to the server">
</sessionState>

Where sqlConnectionString refers to the name of the connection string in the connectionStrings section of web.config which holds the details of the state table. The connection string itself may take up the following format:

<add name="ASPStateConnectionString" connectionString="Data Source=[DB machine name where state DB is stored];Initial Catalog=ASPState;User ID=[db admin user name];Password=[db admin password]"
   providerName="System.Data.SqlClient" />

We’re not done yet, we also need to add a machine and a validation key within the system.web node, that may look something like this:

<machineKey
	validationKey="some long hashed value"
	decryptionKey="another long hashed value"
	validation="SHA1"/>

The validation key is used to validate encrypted data such as the ViewState to ensure it has not been tampered with. The decryption key is used to encrypt and decrypt forms authentication data and viewstate when validation is set to TripleDES.

The default setting for the validation key is AutoGenerate which does exactly what the name applies: the key will be generated automatically by IIS. The default generation mode for the decryption key is IsolateApps. It generates a unique key for each application by using the application ID.

We need this common machine key as we want to run this on several machines so we don’t want the machine key to be automatically generated. The default IsolateApps mode for the decryption key is OK to use in a web farm scenario but the validation key must be common across all servers so we want to produce it ourselves. There are ASP.NET machine key generators out there on the net, you can search yourself, but here are some:

Easiest way to generate MachineKey
Generate ASP.NET Machine Keys
ASP.NET resources

It’s important to emphasise that we want to have static machine key values. The opposite scenario would be that each web farm machine has its own machine key, which will have different values of course and then they access different versions of the session state service.

If you prepare web.config and then deploy your web site using the deployment profile we built in the previous post then the values in the Session State window in IIS will be populated with the values defined in web.config:

State server options filled out in IIS after deploy

Check the machine key in IIS as well:

Machine key icon in IIS

You’ll see that even the validation and decryption keys have also been filled out:

Machine key filled out in IIS

Now that we have set up the out of process state management we can recycle the application pool as much as we like the session state variables will be preserved. If for whatever reason you want to destroy the session state you have the restart the ASP.NET State Service in the Services window or restart the state machine itself.

If you recall from the previous post we set up a batch file that deploys the entire IIS configuration from the staging server to the web farm servers. That will ensure that even the machine keys will be “exported” so that we have one common machine key for the entire farm.

In the next post we’ll start looking at Web Farm Framework.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

26 Responses to Web farms in .NET and IIS part 5: Session state management

  1. Senthil says:

    Thanks for the nice article. I hope you can help me out with this IIS configuration for using sessionstate in SQL. My site is running on web cluster environment. Now I want to change session state to out-proc, in sql server.

    I ran C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe -S (local) -E -sstype c -ssadd -d . It created session db on sql instance and is accessible.

    However, WindowsIdentity.GetCurrent().Name, returns [DefaultAppPool] as current user instead of user domain name(my site uses windows authentication), which ofcourse fails in authentication. If I comment out the <sessionState mode="SQLServer"… in web.config, site works fine getting user's proper domain name.

    Question is what IIS setting needs to be changed in order for sql sessionstate mode to work.

    Thanks in advance.

    • Andras Nemes says:

      Hi Senthil,

      First test if saving a session variable works at all. Save a simple value in a session and check if the same value can be retrieved upon subsequent requests.

      Also, in this post I go through deploying an application on a server farm. You won’t need the whole server farm bit so concentrate on the the session management section: Web farms deployment.

      Check if you find anything that you may have missed.
      //Andras

  2. Mick says:

    Can IIS5.0 configured in web farm or IIS6.0 in IIS5.0 Isolation Mode configured in web farm support session state sharing????

  3. Jim says:

    Hi Andras, thanks for the article. I am currently faced with a Session Issue in my setup. I have two web servers (IIS 7.5) in my farm which use the SQL Server for session state. However the session information that is stored by one doesn’t seem to be accessible by the other. I have checked that that connection strings are the same. The LB is set to round robin. Any pointers would be highly helpful.

  4. Alex says:

    Andras, thank you for the great article! It is very concise yet very informative. I only wish Microsoft and other sites could provide information in this format. I recently developed a new MVC app that leverages session state and I am now facing the issues you described with hosting my app in a web farm. The information you have provided has given me several new options to consider and I appreciate you sharing. I’m off to do some experimentation!

    Take care,
    Alex

  5. demispb says:

    Thanks for the article !!!

  6. Pingback: Using 2 diffrent Razor versions in one solution | Zebley Answers

  7. This isn’t entirely accurate:
    “If you rely on the session state a lot in your code then there will be a lot of read and write operations to and from your SQL server affecting its performance.”
    Session state is only loaded from sql server once per request (as part of the pre-render lifecycle) and then written again only once, after the rendering has taken place.
    Accessing/modifying the session collection during request processing does not cause read/writes against the SQL Server.
    See for example this: https://msdn.microsoft.com/en-us/library/ms178587(v=vs.100).aspx

  8. Good day Sir.

    I’m trying to test/setup a shared session between two web application.
    * I already enabled ASP.net State service,
    * Set Session State of the site (IIS) to State Server (tcpip=localhost:42424)
    * Add session tags in the web.config () on both web application.
    When i press the button from web1 passing a value to session variable and access by web2, no value was retrieve…
    did i missed out something in my settings?
    your help is highly appreciated
    Thank you.

  9. LOMBARDI BPM says:

    Thanks for the nice article.

  10. Pingback: Web farms in .NET and IIS part 5: Session state management | juanhoang

  11. Maddavo says:

    Firstly, thanks for your article… better than anything else I have found. Unfortunately I haven’t been able to apply the information well and I am pulling my hair out trying to get the following working…

    I have an ASP website running in 1 worker process in IIS7 and it uses InProc session state. The session state keeps info for the logged-in user and makes sure that the right stuff is shown to the right user. Many pages within the site check the session state as the very first thing.

    I now want to allocate more worker processes to the website so some users don’t hog the process for others when they’re doing intensive tasks. I realise that I have to use an out-of-process session state.

    I have installed ASP.NET, set the Session Service to start automatically, I have generated machine keys in iis (is there somewhere I have to use these keys?), for a test website I have set the session state to State Server with connection string tcpip=127.0.0.1:42424, opened a port in the firewall for port 42424, set the allowremoteconnection registry key to 1 (although it sounds like I don’t need to since I’m running the state service on the same machine as iis – is that right?)

    When I test, I cannot access the session variables across worker processes. I am at a loss. Is there something on the checklist I’ve missed?

  12. Mikael says:

    Thank you for the article. It is very useful.
    However this

    >> Where sqlConnectionString refers to the name of the connection string in the connectionStrings section of web.config

    is not correct according to documentation
    https://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.100).aspx

    According to docs sqlConnectionString attribute is just a connection string. It does not refer to another connection string.

  13. Pingback: .net Content Management | Home

  14. Praveen says:

    HI Andras Nemes,

    I have a doubt on how to maintain classic asp session in state server mode.

  15. kiquenet says:

    View Losing Session State with ASP.NET/SQL Server http://stackoverflow.com/questions/10555000/losing-session-state-with-asp-net-sql-server

    When you create applications that you expect to share session state using Sql Server, they need the same ID configured in IIS. This is because the session ID that is generated is generated based on the application ID. (Internally the application ID is something like LM/W3SVC/1

    The two servers had different IDs for each application in IIS. The resolution is to change the ID under `Manage Website -> Advanced Settings’ on each server.

    Why they need the same ID configured in IIS ? Why isn’t that obvious in the documentation? Any full documentation in MSDN ?

  16. kiquenet kiquenet says:

    The best marvellous series !!

    Memcached: How-to install in IIS server (web Farm) and setup-configuration?

  17. Madhav says:

    hi Andras,
    I have changed my site session mode in-proc to state server due to session unavailability in other server as it is deployed in web farm architecture.I have done all configuration to change session mode to state server and now its working site fine as well now I am trying to store data in to session but its getting null after post back…

    Could you please help on this.

    thanks,

Leave a comment

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.