blob: 0b9b41be07b61bf18e6be66db1e6bc865bbe6528 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Session Clustering with MongoDB</title><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><meta name="keywords" content="jetty, servlet, servlet-api, cometd, http, websocket, eclipse, maven, java, server, software"><link rel="home" href="index.html" title="Jetty"><link rel="up" href="session-management.html" title="Chapter&nbsp;10.&nbsp;Session Management"><link rel="prev" href="session-clustering-jdbc.html" title="Session Clustering with a Database"><link rel="next" href="session-clustering-infinispan.html" title="Session Clustering with Infinispan"><link xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" rel="shortcut icon" href="images/favicon.ico"><link rel="stylesheet" href="css/highlighter/foundation.css"><script src="js/highlight.pack.js"></script><script>
hljs.initHighlightingOnLoad();
</script><link type="text/css" rel="stylesheet" href="css/font-awesome/font-awesome.min.css"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><tr><td style="width: 25%"><a href="http://www.eclipse.org/jetty"><img src="images/jetty-header-logo.png" alt="Jetty Logo"></a><br><span style="font-size: small">
Version: 9.3.28.v20191105</span></td><td style="width: 50%"></td></tr></table><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Session Clustering with MongoDB</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="session-clustering-jdbc.html"><i class="fa fa-chevron-left" aria-hidden="true"></i> Previous</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;10.&nbsp;Session Management<br><a accesskey="p" href="index.html"><i class="fa fa-home" aria-hidden="true"></i> Home</a></th><td width="20%" align="right">&nbsp;<a accesskey="n" href="session-clustering-infinispan.html">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></a></td></tr></table><hr></div><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="jetty-callout"><h5 class="callout"><a href="http://www.webtide.com/">Contact the core Jetty developers at
<span class="website">www.webtide.com</span></a></h5><p>
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
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="session-clustering-mongodb"></a>Session Clustering with MongoDB</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="session-clustering-mongodb.html#_configuration_2">Configuration</a></span></dt><dt><span class="section"><a href="session-clustering-mongodb.html#_the_nosql_module">The nosql Module</a></span></dt></dl></div><p>Jetty can support session clustering by persisting sessions into <a class="link" href="http://www.mogodb.org" target="_top">MongoDB</a>.
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 <code class="literal">Session.setAttribute()</code> method to ensure that changes are persisted.</p><p>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.</p><p>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.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_configuration_2"></a>Configuration</h3></div></div></div><p>There are two components to session management in Jetty: a session ID manager and a session manager.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">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.</li><li class="listitem">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.</li></ul></div><p>These managers also cooperate and collaborate with the <code class="literal">org.eclipse.jetty.server.session.SessionHandler</code> to enable cross-context dispatch.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_the_nosql_module"></a>The nosql Module</h3></div></div></div><p>When using the jetty distribution, to enable the MongoDB session persistence mechanism, you will first need to enable the nosql <a class="link" href="startup-modules.html" title="Managing Startup Modules">module</a> for your <a class="link" href="quickstart-running-jetty.html#creating-jetty-base" title="Creating a new Jetty Base">base</a> using the <code class="literal">--add-to-start</code> or <code class="literal">--add-to-startd</code> argument to the <a class="link" href="startup.html#startup-overview" title="Startup Overview">start.jar</a>.
This module will automatically download the <code class="literal">mongodb-java-driver</code> and install it to your base&#8217;s <code class="literal">lib/nosql</code> directory.</p><p>As part of the module installation, the necessary mongo java driver jars will be dynamically downloaded and installed to your <code class="literal">${jetty.base}/lib/nosql</code> 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&#8217;ve done that, you will need to prevent Jetty&#8217;s startup checks from detecting the missing jars.
To do that, you can use <code class="literal">--skip-file-validation=nosql</code> argument to start.jar on the command line, or place that line inside <code class="literal">${jetty.base}/start.ini</code> to ensure it is used for every start.</p><p>You will also find the following properties, either in your base&#8217;s <code class="literal">start.d/nosql.ini</code> file or appended to your <code class="literal">start.ini</code>, depending on how you enabled the module:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>## Unique identifier for this node in the cluster
jetty.nosqlSession.workerName=node1
## Interval in seconds between scavenging expired sessions
jetty.nosqlSession.scavenge=1800</code></pre><p>The <code class="literal">jetty.nosqlSession.workerName</code> 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 <span class="strong"><strong>each</strong></span> node to which you install MongoDB session management.</p><p>The <code class="literal">jetty.nosqlSession.scavenge</code> 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.</p><p>These properties are substituted into the configuration of the <code class="literal">MongoDBSessionIdManager</code> and <code class="literal">MongoSessionManager</code>.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_configuring_the_mongosessionidmanager"></a>Configuring the MongoSessionIdManager</h4></div></div></div><p>The nosql module will have installed file called <code class="literal">$\{jetty.home}/etc/jetty-nosql.xml</code>.
This file configures an instance of the <code class="literal">MongoSessionIdManager</code> that will be shared across all webapps deployed on that server.
It looks like this:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"&gt;
&lt;Configure id="Server" class="org.eclipse.jetty.server.Server"&gt;
&lt;!-- ===================================================================== --&gt;
&lt;!-- Configure a MongoSessionIdManager --&gt;
&lt;!-- ===================================================================== --&gt;
&lt;Set name="sessionIdManager"&gt;
&lt;New id="sessionIdMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager"&gt;
&lt;Arg&gt;
&lt;Ref refid="Server"/&gt;
&lt;/Arg&gt;
&lt;Set name="workerName"&gt;&lt;Property name="jetty.nosqlSession.workerName" default="node1"/&gt;&lt;/Set&gt;
&lt;Set name="scavengePeriod"&gt;&lt;Property name="jetty.nosqlSession.scavenge" default="1800"/&gt;&lt;/Set&gt;
&lt;/New&gt;
&lt;/Set&gt;
&lt;/Configure&gt;</code></pre><p>The <code class="literal">MongoSessionIdManager</code> needs access to a MongoDB cluster, and the <code class="literal">jetty-nosql.xml</code> 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&#8217;s an example of a more complex setup to use a remote MongoDB instance:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code> &lt;New id="mongodb" class="com.mongodb.Mongo"&gt;
&lt;Arg&gt;
&lt;New class="java.util.ArrayList"&gt;
&lt;Call name="add"&gt;
&lt;Arg&gt;
&lt;New class="com.mongodb.ServerAddress"&gt;
&lt;Arg type="java.lang.String"&gt;foo.example.com&lt;/Arg&gt;
&lt;Arg type="int"&gt;27017&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;/Call&gt;
&lt;!-- Add more Call statements here as desired --&gt; &lt;/New&gt;
&lt;/Arg&gt;
&lt;Call name="getDB"&gt;
&lt;Arg&gt;HttpSessions&lt;/Arg&gt;
&lt;Call id="sessionDocument" name="getCollection"&gt;
&lt;Arg&gt;sessions&lt;/Arg&gt;
&lt;/Call&gt;
&lt;/Call&gt;
&lt;!-- If you want to configure Jetty to be able to read through the slaves, call the following: --&gt;
&lt;Call name="slaveOk"/&gt;
&lt;/New&gt;
&lt;Set name="sessionIdManager"&gt;
&lt;New id="mongoIdMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager"&gt;
&lt;Arg&gt;
&lt;Ref id="Server"/&gt;
&lt;/Arg&gt;
&lt;Arg&gt;
&lt;Ref id="sessionDocument"/&gt;
&lt;/Arg&gt;
&lt;Set name="workerName"&gt;&lt;Property name="jetty.nosqlSession.workerName" default="node1"/&gt;&lt;/Set&gt;
&lt;Set name="scavengePeriod"&gt;&lt;Property name="jetty.nosqlSession.scavenge" default="1800"/&gt;&lt;/Set&gt;
&lt;/New&gt;
&lt;/Set&gt;</code></pre><p>As Jetty configuration files are direct mappings of XML to Java, it is straight forward to do this in code:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code> Server server = new Server();
...
MongoSessionIdManager idMgr = newMongoSessionIdManager(server);
idMgr.setWorkerName("node1");
idMgr.setScavengePeriod(1800);
server.setSessionIdManager(idMgr);</code></pre><p>The MongoSessionIdManager has slightly different options than some of our more traditional session options.
The <code class="literal">MongoDBSessionIdManager</code> 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 <span class="emphasis"><em>purge</em></span> 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.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">scavengeDelay</span></dt><dd>How long to delay before periodically looking for sessions to scavenge?</dd><dt><span class="term">scavengePeriod</span></dt><dd>How much time after a scavenge has completed should you wait before doing it again?</dd><dt><span class="term">scavengeBlockSize</span></dt><dd>Number of session ids to which to limit each scavenge query.
If you have a very large number of sessions in memory then setting this to a non 0 value may help speed up scavenging by breaking the scavenge into multiple, queries.
The default is 0, which means that all session ids are considered in a single query.</dd><dt><span class="term">purge (Boolean)</span></dt><dd>Do you want to purge (delete) sessions that are invalid from the session store completely?</dd><dt><span class="term">purgeDelay</span></dt><dd>How often do you want to perform this purge operation?</dd><dt><span class="term">purgeInvalidAge</span></dt><dd>How old should an invalid session be before it is eligible to be purged?</dd><dt><span class="term">purgeValidAge</span></dt><dd>How old should a valid session be before it is eligible to be marked invalid and purged?
Should this occur at all?</dd><dt><span class="term">purgeLimit</span></dt><dd>Integer value that represents how many items to return from a purge query.
The default is 0, which is unlimited.
If you have a lot of old expired orphaned sessions then setting this value may speed up the purge process.</dd><dt><span class="term">preserveOnStop</span></dt><dd>Whether or not to retain all sessions when the session manager stops.
Default is <code class="literal">true</code>.</dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_configuring_a_mongosessionmanager"></a>Configuring a MongoSessionManager</h4></div></div></div><p>As mentioned elsewhere, there should be one <code class="literal">MongoSessionManager</code> per context (e.g. webapp).
It will need to reference the single <code class="literal">MongoSessionIdManager</code> configured previously for the Server.</p><p>The way you configure a <a class="link" href="http://www.eclipse.org/jetty/javadoc/9.3.28.v20191105/org/eclipse/jetty/nosql/MongoSessionManager.html" target="_top">org.eclipse.jetty.nosql.mongodb.MongoSessionManager</a> depends on whether you&#8217;re configuring from a <a class="link" href="configuring-specific-webapp-deployment.html#deployable-descriptor-file" title="Jetty Deployable Descriptor XML File">context xml</a> file or a <a class="link" href="jetty-web-xml-config.html" title="jetty-web.xml">jetty-web.xml</a> file or code.
The basic difference is how you get a reference to the Jetty <code class="literal">org.eclipse.jetty.server.Server</code> instance.</p><p>From a context xml file, you reference the Server instance as a Ref:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;Ref name="Server" id="Server"&gt;
&lt;Call id="mongoIdMgr" name="getSessionIdManager"/&gt;
&lt;/Ref&gt;
&lt;Set name="sessionHandler"&gt;
&lt;New class="org.eclipse.jetty.server.session.SessionHandler"&gt;
&lt;Arg&gt;
&lt;New id="mongoMgr" class="org.eclipse.jetty.nosql.mongodb.MongoSessionManager"&gt;
&lt;Set name="sessionIdManager"&gt;
&lt;Ref id="mongoIdMgr"/&gt;
&lt;/Set&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Set&gt;</code></pre><p>From a <code class="literal">WEB-INF/jetty-web.xml</code> file, you can reference the Server instance directly:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;Get name="server"&gt;
&lt;Get id="mongoIdMgr" name="sessionIdManager"/&gt;
&lt;/Get&gt;
&lt;Set name="sessionHandler"&gt;
&lt;New class="org.eclipse.jetty.server.session.SessionHandler"&gt;
&lt;Arg&gt;
&lt;New class="org.eclipse.jetty.nosql.mongodb.MongoSessionManager"&gt;
&lt;Set name="sessionIdManager"&gt;
&lt;Ref id="mongoIdMgr"/&gt;
&lt;/Set&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Set&gt;</code></pre><p>If you&#8217;re embedding this in code:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><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));</code></pre></div></div></div><script type="text/javascript">
SyntaxHighlighter.all()
</script><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="session-clustering-jdbc.html"><i class="fa fa-chevron-left" aria-hidden="true"></i> Previous</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="session-management.html"><i class="fa fa-chevron-up" aria-hidden="true"></i> Top</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="session-clustering-infinispan.html">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></a></td></tr><tr><td width="40%" align="left" valign="top">Session Clustering with a Database&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html"><i class="fa fa-home" aria-hidden="true"></i> Home</a></td><td width="40%" align="right" valign="top">&nbsp;Session Clustering with Infinispan</td></tr></table></div><p xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><div class="jetty-callout">
See an error or something missing?
<span class="callout"><a href="http://github.com/eclipse/jetty.project">Contribute to this documentation at
<span class="website"><i class="fa fa-github" aria-hidden="true"></i> Github!</span></a></span><span style="float: right"><i>(Generated: 2019-11-05)</i></span></div></p></body></html>