22 Managing ASP.NET Session State

This chapter provides instructions for managing ASP.NET session state in a Coherence cluster. The instructions include how to enable and configure the Coherence session provider.

This chapter includes the following sections:

22.1 Overview

Coherence for .NET allows ASP.NET session state to be managed in a Coherence cluster, which has some benefits compared to out-of-the-box options offered by Microsoft:

  • Session state is stored in a highly available Coherence cluster, making sessions resilient to Web server failures

  • Sessions are stored in memory which allows for much faster access than when they are serialized to disk using SQL Server session provider

  • Unlike relational databases, Coherence cluster is easy to scale out to support additional load

  • In some cases, session data can be accessed at in-process speed by leveraging Coherence near caching features

ASP.NET applications are configured to use Coherence for session state management by modifying the web.config file and configuring the custom session state provider. In addition, the Coherence session provider includes configuration options that can significantly improve performance and scalability of applications.

22.2 Setting Up Coherence Session Management

The following steps are required to use Coherence for ASP.NET session management:

After the ASP.NET application and cluster are configured properly, start the cluster and proxy servers to be used by the application and then start the ASP.NET Web application. The sessions are automatically stored within the Coherence cluster.

22.2.1 Enable the Coherence Session Provider

ASP.NET uses a provider model to allow custom session state management implementations. Coherence for .NET implements a custom provider that fulfils the contract defined by Microsoft. To use the Coherence provider, add the following provider configuration to an application's web.config file:

<system.web>
   <sessionState mode="Custom" 
                 customProvider="CoherenceSessionProvider" 
                 cookieless="false" 
                 timeout="20">
      <providers>
         <add name="CoherenceSessionProvider" 
            type="Tangosol.Web.CoherenceSessionStore, Coherence"/> 
      </providers>
   </sessionState>
   ... 
</system.web>

The above example configures an ASP.NET application to use the CoherenceSessionStore provider with the default settings. The Coherence session provider can be customized, as described in this chapter, to take full advantage of its included features.

22.2.2 Configure the Cluster-Side ASP Session Caches

The Coherence session provider requires two cache scheme definitions within the cluster's cache configuration file: A storage cache and an overflow cache. The storage cache is used for storing session data and the overflow cache is used if the session size exceeds the limit specified in the externalAttributeSize attribute of the CoherenceSessionProvider defined in the Web.config file.

When defining the session storage cache and the session overflow cache, the service name must be AspNetSessionCache and the cache names must be aspnet-session-storage and aspnet-session-overflow, respectively. In addition, the storage cache must be configured to use the ConfigurablePofContext class as the serializer. The scheme name and backing map configuration can be configured as required.

The following cache scheme definition creates two distributed caches that are used by the session provider: one for session storage and one for session overflow .

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://schemas.tangosol.com/cache
   assembly://Coherence/Tangosol.Config/cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>aspnet-session-storage</cache-name>
         <scheme-name>aspnet-session-scheme</scheme-name>
      </cache-mapping>
      <cache-mapping>
         <cache-name>aspnet-session-overflow</cache-name>
         <scheme-name>aspnet-session-overflow-scheme</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <distributed-scheme>
         <scheme-name>aspnet-session-scheme</scheme-name>
         <service-name>AspNetSessionCache</service-name>
         <serializer>
            <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
            <init-params>
               <init-param>
                  <param-type>string</param-type>
                  <param-value>coherence-pof-config.xml</param-value>
               </init-param>
            </init-params>
         </serializer>
         <backing-map-scheme>
            <local-scheme/>
         </backing-map-scheme>
         <autostart>true</autostart>
      </distributed-scheme>

      <distributed-scheme>
         <scheme-name>aspnet-session-overflow-scheme</scheme-name>
         <scheme-ref>dist-default</scheme-ref>
         <service-name>AspNetSessionCache</service-name>
         <autostart>true</autostart>
      </distributed-scheme>
   </caching-schemes>
</cache-config>

22.2.3 Configure a Client-Side ASP Session Remote Cache

The Coherence session provider requires an extend client's cache configuration file to include remote cache schemes for the session storage and session overflow caches. As with any remote cache, the cache on the cluster and the cache on the client must use the same name. See "Defining a Remote Cache" for additional details.

The following example configures a client-side ASP session remote cache scheme that is used by the Coherence session provider to store session data on the cluster.

<?xml version='1.0'?>

<cache-config xmlns="http://schemas.tangosol.com/cache"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://schemas.tangosol.com/cache
   assembly://Coherence/Tangosol.Config/cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>aspnet-session-storage</cache-name>
         <scheme-name>extend-direct</scheme-name>
      </cache-mapping>
      <cache-mapping>
         <cache-name>aspnet-session-overflow</cache-name>
         <scheme-name>extend-direct</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>

   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend-direct</scheme-name>
         <service-name>ExtendTcpCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <remote-addresses>
                  <socket-address>
                     <address>localhost</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>30s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

22.2.4 Overriding the Default Session Cache Name

The Coherence session provider's default behavior is to use a remote session cache named aspnet-session-storage. The remote cache example in "Configure a Client-Side ASP Session Remote Cache" demonstrates creating a remote cache with the default name. However, a session provider can be configured to use a remote cache with a name other than the default.

To override the default session cache name, add a cacheName attribute within the provider configuration. The following example specifies a cache named my-session-cache.

<system.web>
   <sessionState mode="Custom" 
                 customProvider="CoherenceSessionProvider" 
                 cookieless="false" 
                 timeout="20">
      <providers>
         <add name="CoherenceSessionProvider" 
              type="Tangosol.Web.CoherenceSessionStore, Coherence"/> 
              cacheName="my-session-cache"
      </providers>
   </sessionState>
   ... 
</system.web>

22.3 Selecting a Session Model

A session model describes how the Coherence session provider physically represents and stores session state in the cluster. The provider includes three different session model implementations out of the box:

  • Traditional Model – Stores all session state as a single entity but serializes and deserializes attributes individually

  • Monolithic Model – Stores all session state as a single entity, serializing and deserializing all attributes as a single operation

  • Split Model – Extends the Traditional Model but separates the larger session attributes into independent physical entities

The traditional model is the default. It is similar to the SessionStateItemCollection provided by ASP.NET - it deserializes session items lazily to avoid deserialization penalty for items that are not accessed. However, there are certain scenarios where monolithic or split model are better choices.

Refer to "Session Model" in Administering HTTP Session Management with Oracle Coherence*Web for details about each model and their pros and cons. The discussion can help determine which model is the best fit for a particular application. The discussion is centered around Coherence*Web; however, the general concepts are the same for ASP.NET Sessions.

22.3.1 Specify the Session Model

The split model is the recommended session model for most applications. However, the traditional model may be more optimal for applications that are known to have small HTTP session objects.

The monolithic model is designed to solve a specific class of problems related to multiple session attributes that have references to the same shared object, and that must maintain that object as a shared object. When migrating to the Coherence session provider from the ASP.NET InProc provider, the monolithic model ensures that all shared objects are serialized and deserialized properly.

To specify the Coherence session provider's session model, add a model attribute within the provider configuration. The following example specifies a split model.

<system.web>
   <sessionState mode="Custom" 
                 customProvider="CoherenceSessionProvider" 
                 cookieless="false" 
                 timeout="20">
      <providers>
         <add name="CoherenceSessionProvider" 
              type="Tangosol.Web.CoherenceSessionStore, Coherence"
              model="split"
              externalAttributeSize="512"/> 
      </providers>
   </sessionState>
   ...
</system.web>

The valid values for the model attribute are traditional, monolithic, split, or a fully qualified name of the class that implements Tangosol.Web.ISessionModelManager interface and provides a constructor that accepts a single Tangosol.IO.ISerializer argument. The interface allows custom model implementations to be created if necessary.

In the example above, the session provider is configured to use the split model. The split model supports externalAttributeSize attribute, which specifies the minimum size (in bytes) of the attributes that should be stored separately. If the externalAttributeSize attribute is omitted, the default value of 1024 bytes is used.

22.3.1.1 Registering the Backing Map Listener

Session attributes are partitioned into two regions when utilizing the split session model. Core HTTP session attributes, such as session ID, creation time, last access, and so on, are managed within one partition and large attributes are split out into another partition. This allows support for very large HTTP session objects without incurring overhead for frequently accessed small attributes.

With the .NET session provider implementation, core attributes and large attributes are stored in separate caches. Therefore; the backing map listener (AspNetSessionStoreProvider$SessionCleanupListener class) is recommended to keep both caches synchronized. This ensures that if a session is terminated explicitly by the user and removed by eviction or expiry, that both the removal of the core and large segments of the session are coherently removed from the two caches.

The following example demonstrates registering the AspNetSessionStoreProvider$SessionCleanupListener backing map listener on the cluster-side ASP .NET session cache:

<caching-schemes>
   <distributed-scheme>
      <scheme-name>aspnet-session-scheme</scheme-name>
      <service-name>AspNetSessionCache</service-name>
      <serializer>
         <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
         <init-params>
            <init-param>
               <param-type>string</param-type>
               <param-value>coherence-pof-config.xml</param-value>
            </init-param>
         </init-params>
      </serializer>
      <backing-map-scheme>
         <local-scheme>
            <class-name>com.tangosol.net.cache.LocalCache</class-name>
            <listener>
               <class-scheme>
                  <class-name>
       com.tangosol.net.internal.AspNetSessionStoreProvider$SessionCleanupListener
                  </class-name>
                  <init-params>
                     <init-param>
                        <param-type>
                           com.tangosol.net.BackingMapManagerContext
                        </param-type>
                        <param-value>{manager-context}</param-value>
                     </init-param>
                  </init-params>
               </class-scheme>
            </listener>
         </local-scheme>
      </backing-map-scheme>
      <autostart>true</autostart>
   </distributed-scheme>

22.4 Specifying a Serializer

The Coherence session provider can be configured to use a specific serializer for serializing session items. To specify a serializer, add a serializer attribute within provider definition. The following example specifies the binary serializer.

<system.web>
   <sessionState mode="Custom" 
                 customProvider="CoherenceSessionProvider" 
                 cookieless="false" 
                 timeout="20">
      <providers>
         <add name="CoherenceSessionProvider" 
              type="Tangosol.Web.CoherenceSessionStore, Coherence"
              model="split"
              externalAttributeSize="512"
              serializer="binary"/> 
      </providers>
   </sessionState>
   ...
</system.web>

The valid values for the serializer attribute are binary (default), pof, or a fully qualified name of the class that implements the Tangosol.IO.ISerializer interface. The interface is used to create a custom serializer if necessary. However, the existing serializers are sufficient more often than not.

22.4.1 Using POF for Session Serialization

Portable Object Format (POF) is the recommended serialization format when using Coherence to manage ASP.NET sessions and provides many benefits over standard .NET binary serialization. In particular, POF serialization is faster and has a significantly more compact format. The compact format typically results in a binary form that is 3 to 5 times smaller than the standard binary serializer. This translates directly into a lower memory footprint within the cluster and can result in significant cost savings.

To use POF, ensure that all custom classes that are stored either directly or indirectly within the session are registered within the POF context and either implement the IPortableObject interface or have an external IPofSerializer configured. For detailed instructions on using POF, see Chapter 17, "Building Integration Objects (.NET)."

The following discussion summarizes some implementation details that should be considered when using POF. For a detailed description of the POF format, see "The PIF-POF Binary Format" in the appendix of the Developing Applications with Oracle Coherence.

When session items are deserialized by the POF serializer, there is no guarantee that the type of the resulting object equals the type of the original value. For example, integer values between -1 and 22 (inclusive) are returned as Int32 values, regardless of the original type, so they may require a cast to the appropriate type.

Collections may also be deserialized to a different type. For example, an ArrayList might be stored within the session, but an immutable object array may be received after the object is read back. This is expected behavior and the reason why the IPofReader interface provides a template to read values as an argument to all methods that read collections from the POF stream.

Session items are not typed and there is no way to specify how they should be deserialized. Therefore, a default collection type is always received. This is typically acceptable when reading from the collection. However, if the collection must be modified, either of the following two options can be used:

  • Create an instance of a mutable collection of a desired type and add elements from the deserialized collection to it. When using this option, do not forget to update corresponding session items with the new collection, or the changes are not saved.

  • Instead of storing "bare" collections directly, create a wrapper class that implements necessary serialization logic and register it within the POF context. This allows full control over collection serialization and can avoid the issues described above.

These steps do require extra work; however, the performance gains and reduced memory footprint are likely worth the trouble.

22.5 Sharing Session State Across Applications

In some cases, it is beneficial to be able to share sessions across ASP.NET applications. By default, a session key is determined by combining the application identifier (as returned by the HostingEnvironment.ApplicationID property) with the session identifier. This effectively prevents session sharing.

The Coherence session provider can be configured to use a specific application identifier. To specify an application identifier, add an applicationId attribute within a provider definition. The following examples specifies MyApplication as the application ID.

<system.web>
   <sessionState mode="Custom" 
                 customProvider="CoherenceSessionProvider" 
                 cookieless="false" 
                 timeout="20">
      <providers>
         <add name="CoherenceSessionProvider" 
              type="Tangosol.Web.CoherenceSessionStore, Coherence"
              applicationId="MyApplication"
              model="split"
              externalAttributeSize="512"
              serializer="pof"/> 
      </providers>
   </sessionState>
   ...
</system.web>

To enable session sharing across the applications, configure multiple applications with the same applicationId and ensure that they share the cookie containing the session identifier.