![]() Version: 9.3.28.v20191105 |
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
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.
There are two components to session management in Jetty: a session ID manager and a session manager.
These managers also cooperate and collaborate with the org.eclipse.jetty.server.session.SessionHandler
to enable cross-context dispatch.
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
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.These properties are applied to the JDBCSessionIdManager
described below.
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);
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.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);
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);