Sessions can play an important part in a server’s performance and its ability to service client requests. When you shut Tomcat down, all session information is usually lost, and sessions that are idle take up valuable working memory until session timeout—which is typically a long period, since some users may leave their computers. Therefore, it’d be useful to save session information across restarts so that users don’t experience a loss of service. Equally, it may be useful to remove idle sessions from memory and store them elsewhere to improve performance.
To solve these problems, Tomcat comes with session managers, which are works in progress, with features and configuration that are subject to change.
You can do the following with the session managers:
You can swap inactive sessions onto disk, thereby releasing the memory consumed by them and making memory available for active sessions.
You can save current sessions to disk when you shut Tomcat down; upon restart, the saved sessions are restored.
You can save sessions lasting beyond a specified threshold period to disk, enabling the system to survive an unexpected crash.
The last two features enable you to give a reliable service to users despite minor server failures or restarts.
Tomcat also allows you to configure clustering so that you can replicate a user’s session across more than one server, thus minimizing the risk of losing their information when one server crashes or becomes unavailable.
The session manager is a context-level component, and you configure it in server.xml using the <Manager> element. Tomcat provides two types of session manager: the standard session manager and the persistent session manager. The standard session manager is the default session manager that Tomcat uses if you don’t specify one of your own, and it doesn’t allow for persistent session management, except that it can retain sessions across a restart. You can still configure a custom standard session manager for a Web application. The persistent session manager allows you to perform all the tasks described previously.
Both types of session manager share two attributes, as shown in Table 7-5.
Attribute | Description | Required? |
---|---|---|
className | The class that implements the session manager. The default is the standard session manager. | No |
distributable | Sets whether the session manager should enforce the restrictions described in the Servlet specification for distributable applications. This means that all session attributes must implement java.io.Serializable. This setting can also be inherited from an application’s web.xml file. The default is false. | No |
If you want to configure the standard implementation, you must set the className attribute to org.apache.catalina.session.StandardManager. Table 7-6 describes its additional attributes.
Attribute | Description | Required? |
---|---|---|
algorithm | Name of the message digest algorithm used to calculate session identifiers produced by this manager. This value must be supported by the java.security.MessageDigest class. The default is MD5. | No |
checkInterval | The number of seconds between checks for expired sessions for this manager. The default is 60. | No |
debug | Tomcat 5.0.x only. The level of debugging detail logged by this manager to the associated logger. Higher numbers generate more detailed output. The default is zero. | No |
entropy | A String value that’s used when seeding the random number generator used to create session identifiers for this manager. If not specified, a semi-useful value is calculated, but a long String value should be specified in security-conscious environments. | No |
maxActiveSessions | The maximum number of active sessions that will be created by this manager. Use -1 (the default) for no limit. | No |
pathname | Absolute or relative (to the work directory for this context, CATALINA_HOME/work/[Engine_name]/[Host_name]/[Webapp_name]) pathname of the file in which session state will be preserved across application restarts, if possible. You may disable restart persistence by setting this attribute to an empty string. The default is SESSIONS.ser. | No |
randomClass | Java class name of the java.util.Random implementation class to use. The default is java.security.SecureRandom. | No |
To configure a persistent session manager, you need to set the className attribute to org.apache.catalina.session.PersistentManager. Table 7-7 describes its additional attributes.
Attribute | Description | Required? |
---|---|---|
algorithm | Name of the message digest algorithm used to calculate session identifiers produced by this manager. This value must be supported by the java.security.MessageDigest class. The default is MD5. | No |
checkInterval | The number of seconds between checks for expired sessions for this manager. The default is 60. | No |
debug | Tomcat 5.0.x only. The level of debugging detail logged by this manager to the associated logger. Higher numbers generate more detailed output. The default is zero. | No |
entropy | A String value that’s used when seeding the random number generator used to create session identifiers for this manager. If not specified, a semi-useful value is calculated, but a long String value should be specified in security-conscious environments. | No |
maxActiveSessions | The maximum number of active sessions that will be created by this manager. Use -1 (the default) for no limit. | No |
maxIdleBackup | The time in seconds since the last access to a session before it’s eligible for being persisted to the session store. -1 (the default) disables this feature. | No |
maxIdleSwap | The time in seconds since the last access to a session before it should be persisted to the session store and taken out of the server’s memory. If this feature is enabled, the time interval specified should be equal to or longer than the value specified for maxIdleBackup. -1 (the default) disables this feature. | No |
minIdleSwap | The time in seconds since the last access to a session before it will be eligible to be persisted to the session store and taken out of the server’s memory. If specified, this value should be less than that specified by maxIdleSwap. -1 (the default) disables this feature and allows the swap at any time. | No |
processExpiresFrequency | Tomcat 5.5 only. Frequency of the session expiration and related manager operations. Manager operations will be done once for the specified amount of background process calls. (That is, the lower the amount, the more often the checks will occur.) The minimum value is 1. The default is 6. | No |
randomClass | Java class name of the java.util.Random implementation class to use. The default is java.security.SecureRandom. | No |
saveOnRestart | Specifies whether all sessions should be persisted and reloaded when Tomcat is shut down and restarted or when this application is reloaded. The default is true. | No |
The differences between the standard session manager and the persistent session manager are illustrated by their attributes. The persistent session manager has options for saving sessions to permanent storage at any point in their life cycle, as well as when you shut down the server, using the maxIdleBackup attribute. It also has options to move sessions out of memory after a certain period, using the maxIdleSwap and minIdleSwap methods. You also have control over whether to save the sessions over a restart using the saveOnRestart attribute.
One crucial difference between the sets of attributes is the absence of a location for storing the session in Table 7-7. In the case of the persistent session manager, you configure the session store using the <Store> subelement. Tomcat allows you to configure two types of store: a file store and a JDBC store.
The file store is the same mechanism used by the standard session manager, except you can use the extra functionality of the persistent session manager. To configure a file store, set the className attribute to org.apache.catalina.session.FileStore and use the attributes from Table 7-8.
Attribute | Description | Required? |
---|---|---|
checkInterval | The interval in seconds between checks for expired sessions among those sessions that are currently swapped out. The default is 60. | No |
className | Java class name of the implementation to use. | Yes |
debug | Tomcat 5.0.x only. The level of debugging detail logged by this store to the associated logger. Higher numbers generate more detailed output. The default is zero. | No |
directory | Absolute or relative (to the temporary work directory for this Web application, CATALINA_HOME/work/[Engine_name]/[Host_name]/ [Webapp_name]) pathname of the directory into which individual session files are written. The default is the temporary work directory assigned by the container. | No |
The JDBC store uses JDBC to store the sessions in a permanent data store, usually a database. To configure a JDBC store, set the className attribute to org.apache.catalina.session.JDBCStore and use the attributes from Table 7-9.
Attribute | Description | Required? |
---|---|---|
checkInterval | The interval in seconds between checks for expired sessions among those sessions that are currently swapped out. The default is 60. | No |
className | Java class name of the implementation to use. | Yes |
connectionURL | The connection URL that will be handed to the configured JDBC driver to establish a connection to the session database. | Yes |
debug | Tomcat 5.0.x only. The level of debugging detail logged by this store to the associated logger. Higher numbers generate more detailed output. The default is zero. | No |
driverName | Java class name of the JDBC driver to be used. | Yes |
sessionAppCol | Name of the database column in the specified session table that contains the engine, host, and context name in the format /Engine/Host/Context. | Yes |
sessionDataCol | Name of the database column in the specified session table that contains the serialized form of all the session attributes for a swapped-out session. The column type must accept a binary object (typically called a BLOB). | Yes |
sessionIdCol | Name of the database column in the specified session table that contains the session identifier of the swapped-out session. The column type must accept character string data of at least as many characters as are contained in session identifiers created by Tomcat (typically 32). | Yes |
sessionLastAccessedCol | Name of the database column in the specified session table that contains the lastAccessedTime property of this session. The column type must accept a Java long (64 bits). | Yes |
sessionMaxInactiveCol | Name of the database column in the specified session table that contains the maxInactiveInterval property of this session. The column type must accept a Java integer (32 bits). | Yes |
sessionTable | Name of the database table to be used for storing swapped out sessions. This table must contain (at least) the database columns that are configured by the other attributes of this element. | Yes |
sessionValidCol | Name of the database column in the specified session table that contains a flag indicating whether this swapped-out session is still valid. The column type must accept a single character. | Yes |
To use the JDBC store, you must create a suitable database in which to store sessions. Listing 7-9 shows an example SQL script for a MySQL database.
Listing 7-9: A SQL Script for MySQL That Creates a JDBC Store-Compatible Database
CREATE TABLE tomcat_sessions ( session_id VARCHAR(100) NOT NULL PRIMARY KEY, valid_session CHAR(1) NOT NULL, max_inactive INT(32) NOT NULL, last_access INT(64) NOT NULL, app_name VARCHAR(255), session_data MEDIUMBLOB, KEY kapp_name(app_name) );
Listing 7-10 shows how to configure a JDBC store in server.xml using this table.
Listing 7-10: A Persistent Session Manager Using a JDBC Store in server.xml
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleBackup="300" minIdleSwap="0" maxIdleSwap="360"> <Store className="org.apache.catalina.session.JDBCStore" connectionURL="jdbc:mysql://localhost:3306/tomcatSession" driverName="com.mysql.jdbc.Driver" sessionAppCol="app_name" sessionDataCol="session_data" sessionIdCol="session_id" sessionLastAccessedCol="last_access" sessionMaxInactiveCol="max_inactive" sessionTable="tomcat_sessions" sessionValidCol="valid_session"/> </Manager>
Notice how the attributes of the <Store> element correspond to the columns created in Listing 7-9. The settings in the <Manager> element tell Tomcat that sessions left for five minutes (300 seconds) are eligible to be backed up to the store, that sessions can be taken out of memory and placed in the store at any time, and that sessions left for six minutes (360 seconds) should be taken out of memory and placed in the store.
If you use this setup and check the database periodically, you’ll see that it’s empty until either the session backup limit is reached or the server is shut down. Once either of these events occurs Tomcat will save the session to the database.
Tomcat also allows you to implement a clustered environment. You can then replicate user sessions across multiple servers to ensure that they don’t lose any data. For clustering to work you’ll have to use some form of load balancing and activate multicasting. Chapter 9 discusses this.
Each Tomcat instance is a node of the cluster and must report in on multicast ping. If a node fails to report for a certain amount of time, the other nodes don’t attempt to replicate any session changes to it. Replicating user sessions across nodes is determined by a set of rules, which is described next. The clustering implementation uses a session manager that overrides any other session manager in the Tomcat instance.
A cluster is defined at the host level using the <Cluster> element, and Tomcat’s default server.xml comes with an example and very serviceable cluster setup. Table 7-10 shows the attributes of the <Cluster> element using the standard implementation org.apache.catalina.cluster.tcp.SimpleTcpCluster.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this cluster. Use org.apache.catalina.cluster.tcp.SimpleTcpCluster. | Yes |
debug | Tomcat 5.0.x only. Set the debug level for this component. The default is zero (no debugging). | No |
expireSessionsOnShutdown | Set to true to remove sessions when this cluster node is shut down. The default is true. | No |
managerClassName | The name of the manager class that looks after the sessions (see earlier for details on session managers). Use org.apache.catalina.cluster.session.DeltaManager, which is the default. | No |
clusterName | Set the name of the cluster to join; if no cluster with this name is present, create one. | No |
notifyListenersOnReplication | Tomcat 5.5 only. Set to true to notify attribute/context listeners upon replication of a session change. These listeners are configured on an application-by-application basis. The default is true. | No |
printToScreen | Set to true to write session information to std.out. The default is false. | No |
protocol | Sets the configurable protocol stack. However, this setting has no function at the time of writing. | No |
useDirtyFlag | Set to false to replicate a session only after a call to setAttribute() or removeAttribute(). In other words, replicate only after session information has changed. Set to true to replicate the session after each request. The default is false. | No |
Listing 7-11 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-11: The Default Cluster Setting in Tomcat 5.5’s server.xml
<Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster" managerClassName="org.apache.catalina.cluster.session.DeltaManager" expireSessionsOnShutdown="false" useDirtyFlag="true" notifyListenersOnReplication="true">
These cluster settings should be the same for all nodes of the cluster.
Now you need to configure this node’s membership credentials using a <Membership> element with the standard org.apache.catalina.cluster.mcast.McastService implementation. This is a subelement of <Cluster>, and Table 7-11 shows its attributes.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this membership setting. Use org.apache.catalina.cluster.mcast.McastService. | Yes |
mcastAddr | The multicast address that this cluster uses to maintain its cohesion. Each node will ping this address to inform the rest of the cluster that it’s still active. This setting has to be the same for all the nodes. | Yes |
mcastBindAddr | This setting binds the multicast socket to a specific address. The default is null. | No |
mcastDropTime | The number of milliseconds from the last multicast heartbeat before a node is considered to be unavailable. | Yes |
mcastFrequency | The number of milliseconds between each multicast heartbeat. | Yes |
mcastPort | The multicast port that this cluster uses to maintain its cohesion. This setting has to be the same for all the nodes. | Yes |
mcastSoTimeout | The multicast read timeout. The read of the pings by other nodes will last as long as this value. The default is -1 (no timeout). | No |
mcastTTL | The multicast time to live if you want to limit your broadcast. The heartbeat ping will last only as long as this value. The default is -1 (no timeout). | No |
Listing 7-12 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-12: The Default Membership Setting in Tomcat 5.5’s server.xml
<Membership className="org.apache.catalina.cluster.mcast.McastService" mcastAddr="228.0.0.4" mcastPort="45564" mcastFrequency="500" mcastDropTime="3000"/>
All these settings should be the same for each node on the cluster.
A node in a cluster receives replication information so that it can synchronize its sessions with the other nodes in the cluster. You achieve this by using a <Receiver> element with the standard org.apache.catalina.cluster.tcp.ReplicationListener implementation in server.xml. These settings are unique to a node, and Table 7-12 describes the relevant attributes.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this receiver. Use org.apache.catalina.cluster.tcp.ReplicationListener. | Yes |
isSenderSynchronized | If set to true, then this node will send an acknowledgment to the replication sender. The default is false. | No |
tcpListenAddress | The TCP address that this node will listen on for session replication. Setting this to auto means that the address is determined with a call to InetAddress.getLocalHost().getHostAddress(). In other words, the local address of the machine. | Yes |
tcpListenPort | The TCP port that this node will listen on for session replication. The default is 0, which lets the system pick up an ephemeral port. | No |
tcpSelectorTimeout | The timeout in milliseconds for the Selector.select() method in case the operating system has a bug in java.nio. Set to 0 for no timeout, which is the default. | No |
tcpThreadCount | The number of threads to handle incoming replication requests. The optimal setting would be the same amount of threads as nodes in this cluster. The default is 0. | No |
Listing 7-13 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-13: The Default Receiver Setting in Tomcat 5.5’s server.xml
<Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener" tcpListenAddress="auto" tcpListenPort="4001" tcpSelectorTimeout="100" tcpThreadCount="6"/>
Just as a node must receive replication information, it must send replication information when one of its sessions changes. You achieve this by using a <Sender> element with the standard org.apache.catalina.cluster.tcp.ReplicationTransmitter implementation in server.xml. Table 7-13 describes these settings.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this sender. Use org.apache.catalina.cluster.tcp.ReplicationTransmitter. | Yes |
replicationMode | Can be pooled, synchronous, or asynchronous. The default is pooled. | No |
The settings for replicationMode are as follows:
synchronous ensures that the thread that executes the request is also the thread that replicates the data to the other nodes. It won’t return until all the nodes in the cluster have received the information. It does this by waiting for an acknowledgment.
pooled uses several sockets in a synchronous way; that is, the data is replicated, then the receiving node sends an acknowledgment. This is the same as synchronous except that it uses a pool of sockets, meaning it’s multithreaded. This is the fastest and safest configuration. Ensure that you have enough threads as advised previously.
asynchronous states that there’s a specific sender thread for each node, so the request thread will queue the replication request and then return to the client. A session is added to the queue, and if the same session already exists in the queue from a previous request, that session will be replaced in the queue instead of replicating two requests. This almost never happens, unless there’s a large network delay.
Listing 7-14 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-14: The Default Sender Setting in Tomcat 5.5’s server.xml
<Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter" replicationMode="pooled" ackTimeout="15000"/>
It’s not always necessary to replicate session state after every request. You’ve already seen the useDirtyFlag attribute of the <Cluster> element. This allows you to replicate session information only after a change in the session state.
You have other ways to save on the overhead and network traffic involved in session replication. One is to not replicate a session after a request for a static resource such as an HTML page or an image. This may not apply in all cases, but you can do it if you want to use a <Valve> element with the org.apache.catalina.cluster.tcp.ReplicationValve implementation. Table 7-14 describes its attributes.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this valve. Use org.apache.catalina.cluster.tcp.ReplicationValve. | Yes |
filter | A set of regular expressions matching file extensions. The valve will intercept requests that match these regular exceptions and bypass the replication mechanism. | Yes |
Listing 7-15 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-15: The Default Replication Valve Setting in Tomcat 5.5’s server.xml.
<Valve className="org.apache.catalina.cluster.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.htm;.*\.html;.*\.txt;"/>
Here you can see that the filter won’t allow replication after requests for images, JavaScript, HTML, and text files.
If you use this valve, the session replication algorithm is as follows. A session is replicated only if all the following conditions are met:
useDirtyFlag is true or setAttribute has been called or removeAttribute has been called.
And a session exists (has been created).
And the request isn’t trapped by the filter attribute of the replication valve.
A node can also deploy and undeploy local Web applications across the cluster using WAR files. This allows you to quickly and easily drop a Web application into the cluster for immediate use and replication. You achieve this by using a <Deployer> element with the standard implementation org.apache.catalina.cluster.deploy.FarmWarDeployer in server.xml. Table 7-15 describes these settings.
Attribute | Description | Required? |
---|---|---|
className | The class that implements this deployer. Use org.apache.catalina.cluster.deploy.FarmWarDeployer. | Yes |
deployDir | The directory where this node will deploy the WAR once it has been dropped into the watchDir. The default is CATALINA_HOME/bin. | No |
tempDir | The temporary work directory for this node. The default is null. | No |
watchEnabled | Set to true to watch the watchDir for WAR files and changes to WAR files. The default is false. | No |
watchDir | The directory where you place new WARs for deployment across the cluster. | Only if watchEnabled is true |
When a WAR is dropped into watchedDir, Tomcat copies it to deployDir and creates a context XML file in CATALINA_HOME/conf/[Engine]/[Host], which is named after the WAR file. The resultant <Context> element’s docBase attribute will point to the WAR file in deployDir. Listing 7-16 shows an example.
Listing 7-16: An Example Context XML File After a Node Has Deployed a WAR
<?xml version='1.0' encoding='utf-8'?> <Context docBase="/C:/JavaStuff/Tomcat/Tomcat29/deployDir/format.war" path="/format"> </Context>
Listing 7-17 shows the setting from Tomcat 5.5’s server.xml.
Listing 7-17: The Default Deployer Setting in Tomcat 5.5’s server.xml
<Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/" deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false"/>
This doesn’t watch for any WAR files and therefore won’t deploy any applications to the cluster.