Version: 9.3.28.v20191105 |

Session Clustering with a Database
Previous | Chapter 10. Session Management Home | Next

##### Contact the core Jetty developers at www.webtide.com

private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ... scalability guidance for your apps and Ajax/Comet projects ... development services for sponsored feature development

## Session Clustering with a Database

Jetty can support session clustering by persisting sessions to a shared database. Each Jetty instance locally caches sessions for which it has received requests, writing any changes to the session through to the database as the request exits the server. Sessions must obey the Serialization contract, and servlets must call the `Session.setAttribute()` method to ensure that changes are persisted.

The persistent session mechanism works in conjunction with a load balancer that supports stickiness. Stickiness can be based on various data items, such as source IP address or characteristics of the session ID or a load-balancer specific mechanism. For those load balancers that examine the session ID, the Jetty persistent session mechanism appends a node ID to the session ID, which can be used for routing.

In this type of solution, the database can become both a bottleneck and a single point of failure. Jetty takes steps to reduce the load on the database (discussed below), but in a heavily loaded environment you might need to investigate other optimization strategies such as local caching and database replication. You should also consult your database vendor’s documentation for information on how to ensure high availability and failover of your database.

### Configuration

There are two components to session management in Jetty: a session ID manager and a session manager.

- The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there can only be one session ID manager per Jetty instance.
- The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.

These managers also cooperate and collaborate with the `org.eclipse.jetty.server.session.SessionHandler` to enable cross-context dispatch.

### The jdbc-session Module

When using the jetty distribution, to enable jdbc session persistence, you will first need to enable the jdbc-session module for your base using the `--add-to-start` or `--add-to-startd` argument to the start.jar.

You will also find the following properties, either in your base’s start.d/jdbc-session.ini file or appended to your start.ini, depending on how you enabled the module:

    ## Unique identifier for this node in the cluster
    jetty.jdbcSession.workerName=node1

    ##Uncomment either the datasource name or driverClass and connectionURL
    #jetty.jdbcSession.datasource=sessions
    jetty.jdbcSession.driverClass=org.apache.derby.jdbc.EmbeddedDriver
    jetty.jdbcSession.connectionURL=jdbc:derby:sessions;create=true

jetty.jdbcSession.workerName
  The name that uniquely identifies this node in the cluster. This value will also be used by the sticky load balancer to identify the node. Don’t forget to change the value of this property on each node on which you enable jdbc session clustering.
jetty.jdbcSession.scavenge
  The time in seconds between sweeps of a task which scavenges old expired sessions. The default is 10 minutess. Increasing the frequency is not recommended as doing so increases the load on the database with very little gain.
jetty.jdbcSession.datasource
  The name of a `javax.sql.DataSource` that gives access to the database that holds the session information. You should configure either this or the jdbc driver information described next.
jetty.jdbcSession.datasource and jetty.jdbcSession.connectionURL
  This is the name of the jdbc driver class, and a jdbc connection url suitable for that driver. You should configure either this or the jdbc datasource name described above.

These properties are applied to the `JDBCSessionIdManager` described below.

#### Configuring the JDBCSessionIdManager

The jdbc-session module will have installed file called `$\{jetty.home}/etc/jetty-jdbc-sessions.xml`. This file configures an instance of the `JDBCSessionIdManager` that will be shared across all webapps deployed on that server. It looks like this:

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">

    <Configure id="Server" class="org.eclipse.jetty.server.Server">

      <!-- ===================================================================== -->
      <!-- Configure a SessionIdManager                                          -->
      <!-- ===================================================================== -->
      <Set name="sessionIdManager">
        <New id="idMgr" class="org.eclipse.jetty.server.session.JDBCSessionIdManager">
          <Arg>
            <Ref refid="Server"/>
          </Arg>
          <Set name="workerName"><Property name="jetty.jdbcSession.workerName" default="node1"/></Set>
          <Set name="scavengeInterval"><Property name="jetty.jdbcSession.scavenge" default="1800"/></Set>

          <!-- ===================================================================== -->
          <!-- Uncomment either the datasource or driver setup and configure         -->
          <!-- ===================================================================== -->

          <!--
              <Set name="DatasourceName"><Property name="jetty.jdbcSession.datasource" default="javax.sql.DataSource/default"/></Set>
          -->
          <!--
            <Call name="setDriverInfo">
              <Arg><Property name="jetty.jdbcSession.driverClass"/></Arg>
              <Arg><Property name="jetty.jdbcSession.connectionURL"/></Arg>
            </Call>
          -->
        </New>
      </Set>

    </Configure>

As well as uncommenting and setting up appropriate values for the properties discussed above, you will also need to edit this file and uncomment either the data source or the driver info elements.

As Jetty configuration files are direct mappings of XML to Java, it is straight forward to do this in code:

    Server server = new Server();
         ...
    JDBCSessionIdManager idMgr = new JDBCSessionIdManager(server);
    idMgr.setWorkerName("node1");
    idMgr.setDriverInfo("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/sessions?user=janb");
    idMgr.setScavengeInterval(600);
    server.setSessionIdManager(idMgr);

##### Configuring the Database Schema

You may find it necessary to change the names of the tables and columns that the JDBC Session management uses to store the session information. The defaults used are:

Table 10.2. Default Values for Session Id Table

table name | JettySessionIds
--- | ---
columns | id

Table 10.3. Default Values for Session Table

table name | JettySessions
--- | ---
columns | rowId, sessionId, contextPath, virtualHost, lastNode, accessTime, lastAccessTime, createTime, cookieTime, lastSavedTime, expiryTime, maxInterval, map

To change these values, use the org.eclipse.jetty.server.session.SessionIdTableSchema and org.eclipse.jetty.server.session.SessionTableSchema classes. These classes have getter/setter methods for the table name and all columns.

Here’s an example of changing the name of `JettySessionsId` table and its single column. This example will use java code, but as explained above, you may also do this via a Jetty xml configuration file:

    JDBCSessionIdManager idManager = new JDBCSessionIdManager(server);

    SessionIdTableSchema idTableSchema = new SessionIdTableSchema();
    idTableSchema.setTableName("mysessionids");
    idTableSchema.setIdColumn("theid");
    idManager.setSessionIdTableSchema(idTableSchema);

In a similar fashion, you can change the names of the table and columns for the `JettySessions` table. Note that both the `SessionIdTableSchema` and the `SessionTableSchema` instances are set on the `JDBCSessionIdManager` class.

    JDBCSessionIdManager idManager = new JDBCSessionIdManager(server);

    SessionTableSchema sessionTableSchema = new SessionTableSchema();
    sessionTableSchema.setTableName("mysessions");
    sessionTableSchema.setIdColumn("mysessionid");
    sessionTableSchema.setAccessTimeColumn("atime");
    sessionTableSchema.setContextPathColumn("cpath");
    sessionTableSchema.setCookieTimeColumn("cooktime");
    sessionTableSchema.setCreateTimeColumn("ctime");
    sessionTableSchema.setExpiryTimeColumn("extime");
    sessionTableSchema.setLastAccessTimeColumn("latime");
    sessionTableSchema.setLastNodeColumn("lnode");
    sessionTableSchema.setLastSavedTimeColumn("lstime");
    sessionTableSchema.setMapColumn("mo");
    sessionTableSchema.setMaxIntervalColumn("mi");
    idManager.setSessionTableSchema(sessionTableSchema);

#### Configuring the JDBCSessionManager

As mentioned elsewhere, there should be one `JDBCSessionManager` per context (e.g. webapp). It will need to reference the single `JDBCSessionIdManager` configured previously for the Server.

The way you configure a `JDBCSessionManager` depends on whether you’re configuring from a context xml file, a `jetty-web.xml` file or code. The basic difference is how you get a reference to the Jetty `org.eclipse.jetty.server.Server` instance.

From a context xml file, you reference the Server instance as a Ref:

      <Ref id="Server">
        <Call id="idMgr" name="getSessionIdManager"/>
      </Ref>
      <Set name="sessionHandler">
        <New class="org.eclipse.jetty.server.session.SessionHandler">
          <Arg>
            <New id="jdbcmgr" class="org.eclipse.jetty.server.session.JDBCSessionManager">
              <Set name="sessionIdManager">
                <Ref id="idMgr"/>
              </Set>
            </New>
          </Arg>
        </New>
      </Set>

From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance directly:

    <Get name="server">
      <Get id="idMgr" name="sessionIdManager"/>
    </Get>
    <Set name="sessionHandler">
      <New class="org.eclipse.jetty.server.session.SessionHandler">
        <Arg>
          <New class="org.eclipse.jetty.server.session.JDBCSessionManager">
            <Set name="sessionIdManager">
              <Ref id="idMgr"/>
            </Set>
          </New>
        </Arg>
      </New>
    </Set>

If you’re embedding this in code:

    //assuming you have already set up the JDBCSessionIdManager as shown earlier
    //and have a reference to the Server instance:

    WebAppContext wac = new WebAppContext();
     ... //configure your webapp context
    JDBCSessionManager jdbcMgr = new JDBCSessionManager();
    jdbcMgr.setSessionIdManager(server.getSessionIdManager());
    SessionHandler sessionHandler = new SessionHandler(jdbcMgr);
    wac.setSessionHandler(sessionHandler);

Previous | Top | Next
Using Persistent Sessions | Home | Session Clustering with MongoDB

See an error or something missing? Contribute to this documentation at Github!(Generated: 2019-11-05)