![]() 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 into MongoDB.
Each Jetty instance locally caches sessions for which it has received requests, writing any changes to the session through to the cluster 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 session persistence 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 traffic on the network needs to be carefully watched and tends to be the bottleneck. You are probably investigating this solution in order to scale to large amount of users and sessions, so careful attention should be paid to your usage scenario. Applications with a heavy write profile to their sessions will consume more network bandwidth than profiles that are predominately read oriented. We recommend using this session manager with largely read based session scenarios.
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 the MongoDB session persistence mechanism, you will first need to enable the nosql module for your base using the --add-to-start
or --add-to-startd
argument to the start.jar.
This module will automatically download the mongodb-java-driver
and install it to your base’s lib/nosql
directory.
As part of the module installation, the necessary mongo java driver jars will be dynamically downloaded and installed to your ${jetty.base}/lib/nosql
directory.
If you need to up or downgrade the version of these jars, then you can delete the jars that were automatically installed and replace them.
Once you’ve done that, you will need to prevent Jetty’s startup checks from detecting the missing jars.
To do that, you can use --skip-file-validation=nosql
argument to start.jar on the command line, or place that line inside ${jetty.base}/start.ini
to ensure it is used for every start.
You will also find the following properties, either in your base’s start.d/nosql.ini
file or appended to your start.ini
, depending on how you enabled the module:
## Unique identifier for this node in the cluster
jetty.nosqlSession.workerName=node1
## Interval in seconds between scavenging expired sessions
jetty.nosqlSession.scavenge=1800
The jetty.nosqlSession.workerName
is the unique name for this Jetty Server instance.
It will be used by the sticky load balancer to uniquely identify the node.
You should change this value on each node to which you install MongoDB session management.
The jetty.nosqlSession.scavenge
property defines the time in seconds between runs of the scavenger: the scavenger is a task which runs periodically to clean out sessions that have expired but become stranded in the database for whatever reason.
These properties are substituted into the configuration of the MongoDBSessionIdManager
and MongoSessionManager
.
The nosql module will have installed file called $\{jetty.home}/etc/jetty-nosql.xml
.
This file configures an instance of the MongoSessionIdManager
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 MongoSessionIdManager -->
<!-- ===================================================================== -->
<Set name="sessionIdManager">
<New id="sessionIdMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager">
<Arg>
<Ref refid="Server"/>
</Arg>
<Set name="workerName"><Property name="jetty.nosqlSession.workerName" default="node1"/></Set>
<Set name="scavengePeriod"><Property name="jetty.nosqlSession.scavenge" default="1800"/></Set>
</New>
</Set>
</Configure>
The MongoSessionIdManager
needs access to a MongoDB cluster, and the jetty-nosql.xml
file assumes the defaults of localhost and default MongoDB port.
If you need to configure something else, you will need to edit this file.
Here’s an example of a more complex setup to use a remote MongoDB instance:
<New id="mongodb" class="com.mongodb.Mongo">
<Arg>
<New class="java.util.ArrayList">
<Call name="add">
<Arg>
<New class="com.mongodb.ServerAddress">
<Arg type="java.lang.String">foo.example.com</Arg>
<Arg type="int">27017</Arg>
</New>
</Arg>
</Call>
<!-- Add more Call statements here as desired --> </New>
</Arg>
<Call name="getDB">
<Arg>HttpSessions</Arg>
<Call id="sessionDocument" name="getCollection">
<Arg>sessions</Arg>
</Call>
</Call>
<!-- If you want to configure Jetty to be able to read through the slaves, call the following: -->
<Call name="slaveOk"/>
</New>
<Set name="sessionIdManager">
<New id="mongoIdMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager">
<Arg>
<Ref id="Server"/>
</Arg>
<Arg>
<Ref id="sessionDocument"/>
</Arg>
<Set name="workerName"><Property name="jetty.nosqlSession.workerName" default="node1"/></Set>
<Set name="scavengePeriod"><Property name="jetty.nosqlSession.scavenge" default="1800"/></Set>
</New>
</Set>
As Jetty configuration files are direct mappings of XML to Java, it is straight forward to do this in code:
Server server = new Server();
...
MongoSessionIdManager idMgr = newMongoSessionIdManager(server);
idMgr.setWorkerName("node1");
idMgr.setScavengePeriod(1800);
server.setSessionIdManager(idMgr);
The MongoSessionIdManager has slightly different options than some of our more traditional session options.
The MongoDBSessionIdManager
has the same scavenge timers which govern the setting of a valid session to invalid after a certain period of inactivity.
New to this session id manager is the extra purge setting which governs removal from the MongoDB cluster.
This can be configured through the purge option. Purge is by default set to true and by default runs daily for each node on the cluster.
Also able to be configured is the age in which an invalid session will be retained which is set to 1 day by default.
This means that invalid sessions will be removed after lingering in the MongoDB instance for a day.
There is also an option for purging valid sessions that have not been used recently.
The default time for this is 1 week. You can disable these behaviors by setting purge to false.
true
.As mentioned elsewhere, there should be one MongoSessionManager
per context (e.g. webapp).
It will need to reference the single MongoSessionIdManager
configured previously for the Server.
The way you configure a org.eclipse.jetty.nosql.mongodb.MongoSessionManager depends on whether you’re configuring from a context xml file or 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 name="Server" id="Server">
<Call id="mongoIdMgr" name="getSessionIdManager"/>
</Ref>
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler">
<Arg>
<New id="mongoMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionManager">
<Set name="sessionIdManager">
<Ref id="mongoIdMgr"/>
</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="mongoIdMgr" name="sessionIdManager"/>
</Get>
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler">
<Arg>
<New class="org.eclipse.jetty.nosql.mongodb.MongoSessionManager">
<Set name="sessionIdManager">
<Ref id="mongoIdMgr"/>
</Set>
</New>
</Arg>
</New>
</Set>
If you’re embedding this in code:
//assuming you have already set up the MongoSessionIdManager as shown earlier
//and have a reference to the Server instance:
WebAppContext wac = new WebAppContext();
... //configure your webapp context
MongoSessionManager mongoMgr = new MongoSessionManager();
mongoMgr.setSessionIdManager(server.getSessionIdManager());
wac.setSessionHandler(new SessionHandler(mongoMgr));