Gal Ratner
Gal Ratner is a Techie who lives and works in Los Angeles CA and Austin TX. Follow galratner on Twitter Google
Sharing memory session between servers

Session variables hold per user information. Unlike cookies, sessions store information on the server rather than on the client. The client holds a session cookie with the client’s session ID and at the time of an HTTP request, the server accesses the client’s session ID and retrieves the session data.


The default implementation of session has the web server holding the information in memory. This implementation as fast as it is has some drawbacks: Recycling your app pool or restarting IIS will abandon all of the sessions currently in memory. Sharing sessions between web servers is also not possible and when load balancing traffic between servers we need to resort to “sticky sessions”, a method in which all client requests will be redirected to the same physical server as the first request. This would enable us to still use default sessions, however, it will not solve the first issue I mentioned and we are still running the risk of overloading a server’s memory under heavy traffic load when some of our servers are slow to respond.


ASP.NET supports four session storage options:


Off: Session state is disabled.
InProc: Session state is in process with an ASP.NET worker process.
StateServer: Session state is using the out-of-process ASP.NET State Service to store state information.
SQLServer: Session state is using an out-of-process SQL Server database to store state information.
Custom: Session state is using a custom data store to store session-state information.
In this article I am going to discuss the StateServer option in which the server holds session data in memory and outside the web server. This allows the presents of a dedicated session server and sharing of session data between all servers.
The internal .NET implementation of StateServer resides in System.Web.SessionState.OutOfProcSessionStateStore and internally relies on socket connections methods in webengine.dll. Since all session data passes through sockets, all data must be serializable.


In order to activate the session store we need to run the aspnet_state.exe service.

 

In our web.config  we need to set the session state mode:
<configuration>
  <system.web>
    <sessionState mode="StateServer"
      stateConnectionString="tcpip=SampleStateServer:42424"
      cookieless="false"
      timeout="20"/>
  </system.web>
</configuration>

The last step would be to sync up all of our servers machine keys in our web.config.


machineKey configures algorithms and keys to use for encryption, decryption, and validation of forms-authentication data and view-state data, and for out-of-process session state identification.
We need to synch two keys:
validationKey: used to generate out-of-process, application-specific session IDs to ensure that session-state variables are isolated between sessions.
decryptionKey: Specifies the key that is used to encrypt and decrypt data or the process by which the key is generated.
This is how our machineKey will look like:


<machineKey
    validationKey="32E35872597989D14CC1D5D9F5B1E94238D0EE32CF10AA2D2059533DF6035F4F"
    decryptionKey="B179091DBB2389B996A526DE8BCD7ACFDBCAB04EF1D085481C61496F693DF5F4"
/>


machineKey is located in our <system.web> tag.
Syncing our machineKey is done since session information is encrypted and we need all the web servers to be able to encrypt and decrypt the data.
You can generate new keys using the following code:

class Program
	{
		static void Main(string[] args)
		{
			CreateMachineKey(24, 64);
		}
 
		public static void CreateMachineKey(int decryption, int validation)
		{
			string decryptionKey = CreateKey(decryption);
			string validationKey = CreateKey(validation);
			Console.WriteLine(@"<machineKey validationKey=""{0}"" decryptionKey=""{1}"" validation=""SHA1""/>", validationKey, decryptionKey);
			Console.ReadLine();
		}
 
		public static string CreateKey(int numBytes)
		{
			RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
			byte[] buff = new byte[numBytes - 1];
			rng.GetBytes(buff);
			return BytesToHexString(buff);
		}
 
		public static string BytesToHexString(byte[] bytes)
		{
			StringBuilder hexString = new StringBuilder(64);
			for (int i = 0; i < bytes.Length; i++)
				hexString.Append(String.Format("{0:X2}", bytes[i]));
			int counter;
			return hexString.ToString();
		}
	}



Once we have it all configured we can give our website a try and make sure all of our session variables are working.
If we encounter any empty session values we will most likely need to examine serialization issues in our session objects.


Conclusion
Keeping sessions in a dedicated session state server can help alleviate memory pressure on your web server as well as help with memory data duplication. It is also a good practice with any new website development to use serializable session objects as pre planning for StateServer mode.

Shout it


Posted 1 Jun 2011 9:25 PM by Gal Ratner
Filed under: ,

Powered by Community Server (Non-Commercial Edition), by Telligent Systems