CodeKicks.com
Focus on Microsoft Technologies - Tutorials, Articles, Code Samples.

Wednesday, August 30, 2006

Session Management in ASP.NET

Server-side state-management techniques: cookie-based sessions, cookie-less sessions, read-only sessions, application variables, static variables, out-of-process (ASP.NET State Service), and out-of-process (SQL Server).

 The first time a user requests a page in your application, ASP.NET creates a session environment for this user on the Web server. ASP.NET exposes the Session object as a collection for you to store and retrieve state information for this user. You use the Session object like any other collection to store anything from simple data types to complex objects and structures. ASP.NET assigns a unique ID for each session to isolate an individual user's private state information. ASP.NET uses a temporary cookie (which is stored in client RAM, then discarded when the user closes the browser) to pass the session ID between the browser and the Web server. It's important to understand that only the session ID—a small value—gets passed between client and server. The state information itself is stored on the Web server in RAM without ever crossing the wire (see Figure 1). After a period of inactivity from the client (20 minutes by default), user sessions time out and are discarded from server RAM. Here's a small example of how to use the Session object in PageA.aspx.vb:

 

Sessions don't work at all if the user has disabled cookies, because the Web server uses cookies to pass the session ID. These issues have steered classic ASP developers away from the Session object. Fortunately, ASP.NET has decorated the Session object with two new features that address these problems: cookie-less sessions and out-of-process state management.

 

As the name implies, cookie-less sessions enable the Session object even if the user turns off cookie support in the browser. Enabling this feature is as simple as setting an attribute in the web.config file:

 

<sessionState ...

   cookieless="true" ...

/>

 

Then, ASP.NET auto-matically inserts the session ID into the URL of every link in your application, rather than using a cookie to pass the session ID back and forth over the wire. For example, http://localhost/PageA.aspx becomes http://localhost/(w1fmnnqzif4k1bnuarqrwinq)/PageA.aspx.

 

ASP.NET is smart enough to insert the session ID into the URLs of every anchor tag and form action in your application. Cookie-less sessions guarantee that your application functions, regardless of cookie support on the client. If you need to "manufacture" a URL for passing to an external application, you can use the Response.ApplyAppPathModifier method, which accepts any URL and "munges" it with the session ID. In this way, the external application can call back into your application with the appropriate session ID:

 

Dim sMungedUrl As String = _

   Response.ApplyAppPathModifier( _

   "PageA.aspx")

 

 

Scale Up or Scale Out

Out-of-process state management deals with the issue of scalability. You have two ways to handle the demand of many sessions with lots of state information. The first is to "scale up"—add more RAM and more CPUs to the server until you hit the ceiling on maximum memory and processors. The second is to "scale out"—add more servers. A scaled-out configuration is commonly referred to as a Web farm, where each server in the farm runs the same ASP.NET application, and the collection of servers appears to the outside world as a single site. This provides dynamic load-balancing by distributing client demand evenly across a set of servers.

 

Classic ASP applications can't take full advantage of Web farms. Session state is stored in RAM, so the user must always be directed to the server that stores his state information. Once a user's initial page request hits a server, the user is tied to that particular server for all subsequent page requests.

 

ASP.NET solves this problem by providing "out-of-process" state management. This feature removes session state from the Web server and places it in another process on another machine called the state server (see Figure 2). The Web servers in the farm communicate with the state server to store and retrieve session information. True load-balancing is achieved, and any Web server in the farm can process any page request issued by any client at any time. Furthermore, Web servers can be taken down and brought back online without disrupting active user sessions.

 

 Ssmgt

 

 

ASP.NET generates unique IDs for each machine in the network automatically, by default. You configure a Web farm by setting each server's machine key to the same value. Edit the machine.config file (located in the C:\winnt\Microsoft.NET\Framework\vn.n.n\CONFIG directory) on each server and find the machineKey tag. Set the validationKey and decryptionKey attributes to a hex value (any value will do, as long as you use the same value on all machines):

 

<machineKey    validationKey="0123456789ABCDEF0123

   456789ABCDEF0123456789ABCDEF"

   decryptionKey="FEDCBA9876543210FEDC

   BA9876543210FEDCBA9876543210"

   :

/>

 

You have two options for configuring a state server: Use the ASP.NET State Service or use SQL Server. The ASP.NET State Service uses RAM on the state server to store session information for all Web servers in the farm. This service is off by default; in a production environment, set its startup mode to "Automatic" in the Computer Management services console. Then, set two attributes in the web.config file of each Web server in the farm to enable the feature and identify the state server's IP address (leave the port at the default value of 42424):

 

<sessionState

   mode="StateServer"

   stateConnectionString=

   "tcpip=192.168.0.7:42424"

   ...

/>

Achieve Maximum Scalability

The SQL Server option stores session information in a database on the state server, and is available only if you have a SQL Server license. Although you incur a slight performance penalty by accessing a database rather than RAM, this option provides the greatest scalability, because database sizes are virtually unlimited compared with RAM. SQL Server uses caching extensively, so recently accessed state information is frequently retrieved from RAM anyway, which boosts performance. Furthermore, ASP.NET is smart enough to use a varbinary column for state information smaller than 7,000 bytes, and it uses a less efficient image column only if the state information exceeds 7,000 bytes. One caveat: You must ensure that any objects you store in Session are serializable if you want to use this feature.

 

Use Query Analyzer to execute the script file InstallSqlState.sql (located in the C:\winnt\Microsoft.NET\

Framework\vn.n.n folder) to create the stored procedures ASP.NET requires for using SQL Server. ASP.NET uses tempdb to store session information for performance reasons, so sessions are lost if SQL Server goes down. You can modify the script (at your own risk) to use another database if you want truly durable sessions that survive server reboots.

 

Set two attributes in the web.config file of each of the farm's Web servers to enable the feature and identify SQL Server's IP address:

 

<sessionState

   mode="SqlServer"

   sqlConnectionString="data

      source=192.168.0.7;

   Trusted_Connection=yes"

   ...

/>

 

You can improve performance slightly for pages that only need to read but not write Session variables by including the EnableSessionState="ReadOnly" attribute in the <%@ Page %> tag directive. You can also turn off sessions for pages that don't need them by specifying EnableSessionState="False" for even better performance of those pages.

 

Use the Application object to store global application data all users will share. The Application object must be locked down while you write to it, as in classic ASP. A typical use is to store connection strings:

 

Application.Lock()

Application("dbConn") = _

   "initial catalog=pubs;" & _

   "data source=localhost;" & _

   "integrated security=SSPI;"

Application.UnLock()

 

 

Another less obvious option for storing global data is to use static variables. They have performance advantages over the Application object, because they're strongly typed and don't require searching through a collection. Your compiled code executes inside the always-running aspnet_wp process, so static variables in your application preserve their values between client requests. Implement this technique by defining a module (which is really a static class) to store your global variables:

 

Module GlobalVariables

   Public DbConn As String

End Module

 

In global.asax, initialize the variables in the Application_Start procedure for all sessions running your application:

 

Sub Application_Start _

   (ByVal sender As Object, ByVal e _

   As EventArgs)

   GlobalVariables.DbConn = _

      "initial catalog=pubs;" & _

      "data source=localhost;" & _

      "integrated security=SSPI;"

End Sub

 

Thanks to ASP.NET, state management no longer needs to be a laborious chore when you build Web applications. Experiment with all seven server-side techniques to take best advantage of them when client-side, state-management techniques won't fit the bill.

 

 

ASP.NET provides three methods to store session information:

 

  • In Process (InProc)
  • State Server
  • SQL Server

  

 

Advantages

Disadvantages

In Process

  1. Default.
  2. Fastest.
  3. Simplest.

<sessionState mode="InProc"  cookieless="false" timeout="20" />

  1. Session information lost if the worker process (either aspnet_wp.exe or w3wp.exe) is restarted (for a developer this includes a rebuild on the development machine).
  2. Not suitable for web-farms.

State Server

  1. Tolerant of worker process crashes.
  2. Suitable for web-farms.

<sessionState mode="StateServer"  stateConnectionString="tcpip=server1:42424"  cookieless="false"  timeout="20" />

The default entry for stateConnectionString is "stateConnectionString="tcpip=127.0.0.1:42424", this is reasonable if the state server is on the same server (The IP address 127.0.0.1 is by definition the local machine). If however you are running in a web-server environment then it is vitally important that you set the server name, so substitute the name of a server for "server1" in the above example. Otherwise each server will communicate with the state server process running locally and session information will not be shared between servers.

 

You also need to ensure that the state server is running on the chosen server. Do this by looking at the services on the server and ensure that "ASP.NET State Service" is started and set to "Automatic" start-up.

  1. Slower than In-Process.
  2. State is maintained on a single server, and thus a single point of failure (only an issue if site up-time and fault tolerance is an issue)

SQL Server

  1. Tolerant of worker process crashes.
  2. Suitable for web-farms.
  3. Supports failover clusters.
  1. Requires SQL Server.
  2. Slowest method.
  3. Most complex to set up

 

Post a Comment