HTTP Session Management
Sessions are a concept within the Servlet API which allow requests to store and retrieve information across the time a user spends in an application.
Session Architecture
Jetty session support has been architected to provide a core implementation that is independent of the Servlet specification.
This allows programmers who use core Jetty - without the Servlet API - to still have classic Servlet session-like support for their Request
s and Handler
s.
These core classes are adapted to each of the various Servlet specification environments to deliver classic HttpSession
s for Servlet
s,`Filter``s, etc
Full support for the session lifecycle is supported, in addition to L1 and L2 caching, and a number of pluggable options for persisting session data.
Here are some of the most important concepts that will be referred to throughout the documentation:
- SessionIdManager
-
responsible for allocation of unique session ids.
- HouseKeeper
-
responsible for orchestrating the detection and removal of expired sessions.
- SessionManager
-
responsible for managing the lifecycle of sessions.
- SessionHandler
-
an implementation of
SessionManager
that adapts sessions to either the core or Servlet specification environment. - SessionCache
-
an L1 cache of in-use
ManagedSession
objects - Session
-
a session consisting of
SessionData
that can be associated with aRequest
- ManagedSession
-
a
Session
that supports caching and lifecycle management - SessionData
-
encapsulates the attributes and metadata associated with a
Session
- SessionDataStore
-
responsible for creating, persisting and reading
SessionData
- CachingSessionDataStore
-
an L2 cache of
SessionData
Diagrammatically, these concepts can be represented as:
The SessionIdManager
There is a maximum of one SessionIdManager
per Server
instance.
Its purpose is to generate fresh, unique session ids and to coordinate the re-use of session ids amongst co-operating contexts.
The SessionIdManager
is agnostic with respect to the type of clustering technology chosen.
Jetty provides a default implementation - the DefaultSessionIdManager - which should meet the needs of most users.
The DefaultSessionIdManager
A single instance of the DefaultSessionIdManager
should be created and registered as a bean on the Server
instance so that all SessionHandler
's share the same instance.
This is done by the Jetty session
module, but can be done programmatically instead.
As a fallback, when an individual SessionHandler
starts up, if it does not find the SessionIdManager
already present for the Server
it will create and register a bean for it.
That instance will be shared by the other SessionHandler
s.
The most important configuration parameter for the DefaultSessionIdManager
is the workerName
, which uniquely identifies the server in a cluster.
If a workerName
has not been explicitly set, then the value is derived as follows:
node[JETTY_WORKER_NAME]
where JETTY_WORKER_NAME
is an environment variable whose value can be an integer or string.
If the environment variable is not set, then it defaults to 0
, yielding the default workerName
of "node0"
.
It is essential to change this default if you have more than one Server
.
Here is an example of explicitly setting up a DefaultSessionIdManager
with a workerName
of server3
in code:
Server server = new Server();
DefaultSessionIdManager idMgr = new DefaultSessionIdManager(server);
//you must set the workerName unless you set the env viable JETTY_WORKER_NAME
idMgr.setWorkerName("server3");
server.addBean(idMgr, true);
The HouseKeeper
The DefaultSessionIdManager
creates a HouseKeeper, which periodically scans for, and eliminates, expired sessions (referred to as "scavenging").
The period of the scan is controlled by the setIntervalSec(int)
method, defaulting to 600secs.
Setting a negative or 0 value prevents scavenging occurring.
The |
Here is an example of creating and configuring a HouseKeeper
for the DefaultSessionIdManager
in code:
Server server = new Server();
DefaultSessionIdManager idMgr = new DefaultSessionIdManager(server);
idMgr.setWorkerName("server7");
server.addBean(idMgr, true);
HouseKeeper houseKeeper = new HouseKeeper();
houseKeeper.setSessionIdManager(idMgr);
//set the frequency of scavenge cycles
houseKeeper.setIntervalSec(600L);
idMgr.setSessionHouseKeeper(houseKeeper);
Implementing a Custom SessionIdManager
If the DefaultSessionIdManager
does not meet your needs, you can extend it, or implement the SessionIdManager
interface directly.
When implementing a SessionIdManager
pay particular attention to the following:
-
the
getWorkerName()
method must return a name that is unique to theServer
instance. TheworkerName
becomes important in clustering scenarios because sessions can migrate from node to node: theworkerName
identifies which node was last managing aSession
. -
the contract of the
isIdInUse(String id)
method is very specific: a session id may only be reused iff it is already in use by another context. This restriction is important to support cross-context dispatch. -
you should be very careful to ensure that the
newSessionId(HttpServletRequest request, long created)
method does not return duplicate or predictable session ids.
The SessionHandler
A SessionHandler
is a Handler
that implements the SessionManager
, and is thus responsible for the creation, maintenance and propagation of sessions.
There are SessionHandlers
for both the core and the various Servlet environments.
Note that in the Servlet environments, each ServletContextHandler
or WebAppContext
has at most a single SessionHandler
.
Both core and Servlet environment SessionHandlers
can be configured programmatically.
Here are some of the most important methods that you may call to customize your session setup.
Note that in Servlet environments, some of these methods also have analogous Servlet API methods and/or analogous web.xml
declarations and also equivalent context init params.
These alternatives are noted below.
- setCheckingRemoteSessionIdEncoding(boolean) [Default:false]
-
This controls whether response urls will be encoded with the session id as a path parameter when the URL is destined for a remote node.
Servlet environment alternatives:-
org.eclipse.jetty.session.CheckingRemoteSessionIdEncoding
context init parameter
-
- setMaxInactiveInterval(int) [Default:-1]
-
This is the amount of time in seconds after which an unused session may be scavenged.
Servlet environment alternatives:-
<session-config><session-timeout/></session-config>
element inweb.xml
(NOTE! this element is specified in minutes but this method uses seconds). -
ServletContext.setSessionTimeout(int)
where the timeout is configured in minutes.
-
- setHttpOnly(boolean) [Default:false]
-
If
true
, the session cookie will not be exposed to client-side scripting code.
Servlet environment alternatives:-
SessionCookieConfig.setHttpOnly(boolean)
-
<session-config><cookie-config><http-only/></cookie-config></session-config>
element inweb.xml
-
- setMaxAge(int) [Default:-1]
-
This is the maximum number of seconds that the session cookie will be considered to be valid. By default, the cookie has no maximum validity time. See also refreshing the session cookie.
Servlet environment alternatives:-
ServletContext.getSessionCookieConfig().setMaxAge(int)
-
org.eclipse.jetty.session.MaxAge
context init parameter
-
- setSessionDomain(String) [Default:null]
-
This is the domain of the session cookie.
Servlet environment alternatives:-
ServletContext.getSessionCookieConfig().setDomain(String)
-
<session-config><cookie-config><domain/></cookie-config></session-config>
element inweb.xml
-
org.eclipse.jetty.session.SessionDomain
context init parameter
-
- setSessionPath(String) [Default:null]
-
This is used when creating a new session cookie. If nothing is configured, the context path is used instead, defaulting to
/
.
Servlet environment alternatives:-
ServletContext.getSessionCookieConfig().setPath(String)
-
<session-config><cookie-config><path/></cookie-config></session-config>
element inweb.xml
-
org.eclipse.jetty.session.SessionPath
context init parameter
-
Statistics
Some statistics about the sessions for a context can be obtained from the SessionHandler
, either by calling the methods directly or via JMX:
- getSessionsCreated()
-
This is the total number of sessions that have been created for this context since Jetty started.
- getSessionTimeMax()
-
The longest period of time a session was valid in this context before being invalidated.
- getSessionTimeMean()
-
The average period of time a session in this context was valid.
- getSessionTimeStdDev()
-
The standard deviation of the session validity times for this context.
- getSessionTimeTotal()
-
The total time that all sessions in this context have remained valid.
The SessionCache
There is one SessionCache
per SessionManager
, and thus one per context.
Its purpose is to provide an L1 cache of ManagedSession
objects.
Having a working set of ManagedSession
objects in memory allows multiple simultaneous requests for the same session (ie the same session id in the same context) to share the same ManagedSession
object.
A SessionCache
uses a SessionDataStore
to create, read, store, and delete the SessionData
associated with the ManagedSession
.
There are two ways to create a SessionCache
for a SessionManager
:
-
allow the
SessionManager
to create one lazily at startup. TheSessionManager
looks for aSessionCacheFactory
bean on theServer
to produce theSessionCache
instance. It then looks for aSessionDataStoreFactory
bean on theServer
to produce aSessionDataStore
instance to use with theSessionCache
. If noSessionCacheFactory
is present, it defaults to creating aDefaultSessionCache
. If noSessionDataStoreFactory
is present, it defaults to creating aNullSessionDataStore
. -
pass a fully configured
SessionCache
instance to theSessionManager
. You are responsible for configuring both theSessionCache
instance and itsSessionDataStore
More on SessionDataStore
s later, this section concentrates on the SessionCache
and SessionCacheFactory
.
The AbstractSessionCache provides most of the behaviour of SessionCache
s.
If you are implementing a custom SessionCache
it is strongly recommended that you extend this class because it implements the numerous subtleties of the Servlet specification.
Some of the important behaviours of SessionCache
s are:
- eviction
-
By default,
ManagedSession
s remain in a cache until they are expired or invalidated. If you have many or large sessions that are infrequently referenced you can use eviction to reduce the memory consumed by the cache. When a session is evicted, it is removed from the cache but it is not invalidated. If you have configured aSessionDataStore
that persists or distributes the session in some way, it will continue to exist, and can be read back in when it needs to be referenced again. The eviction strategies are:- NEVER_EVICT
-
This is the default, sessions remain in the cache until expired or invalidated.
- EVICT_ON_SESSION_EXIT
-
When the last simultaneous request for a session finishes, the session will be evicted from the cache.
- EVICT_ON_INACTIVITY
-
If a session has not been referenced for a configurable number of seconds, then it will be evicted from the cache.
- saveOnInactiveEviction
-
This controls whether a session will be persisted to the
SessionDataStore
if it is being evicted due to the EVICT_ON_INACTIVITY policy. Usually sessions are written to theSessionDataStore
whenever the last simultaneous request exits the session. However, asSessionDataStore
s` can be configured to skip some writes, this option ensures that the session will be written out. - saveOnCreate
-
Usually a session will be written through to the configured
SessionDataStore
when the last request for it finishes. In the case of a freshly created session, this means that it will not be persisted until the request is fully finished. If your application uses context forwarding or including, the newly created session id will not be available in the subsequent contexts. You can enable this feature to ensure that a freshly created session is immediately persisted after creation: in this way the session id will be available for use in other contexts accessed during the same request. - removeUnloadableSessions
-
If a session becomes corrupted in the persistent store, it cannot be re-loaded into the
SessionCache
. This can cause noisy log output during scavenge cycles, when the same corrupted session fails to load over and over again. To prevent his, enable this feature and theSessionCache
will ensure that if a session fails to be loaded, it will be deleted. - invalidateOnShutdown
-
Some applications want to ensure that all cached sessions are removed when the server shuts down. This option will ensure that all cached sessions are invalidated. The
AbstractSessionCache
does not implement this behaviour, a subclass must implement the SessionCache.shutdown() method. - flushOnResponseCommit
-
This forces a "dirty" session to be written to the
SessionDataStore
just before a response is returned to the client, rather than waiting until the request is finished. A "dirty" session is one whose attributes have changed, or it has been freshly created. Using this option ensures that all subsequent requests - either to the same or a different node - will see the latest changes to the session.
Jetty provides two SessionCache
implementations: the DefaultSessionCache and the NullSessionCache.
The DefaultSessionCache
The DefaultSessionCache retains ManagedSession
objects in memory in a ConcurrentHashMap
.
It is suitable for non-clustered and clustered deployments.
For clustered deployments, a sticky load balancer is strongly recommended, otherwise you risk indeterminate session state as the session bounces around multiple nodes.
It implements the SessionCache.shutdown() method.
It also provides some statistics on sessions, which are convenient to access either directly in code or remotely via JMX:
- current sessions
-
The DefaultSessionCache.getSessionsCurrent() method reports the number of sessions in the cache at the time of the method call.
- max sessions
-
The DefaultSessionCache.getSessionsMax() method reports the highest number of sessions in the cache at the time of the method call.
- total sessions
-
The DefaultSessionCache.getSessionsTotal() method reports the cumulative total of the number of sessions in the cache at the time of the method call.
If you create a DefaultSessionFactory and register it as a Server
bean, a SessionManger
will be able to lazily create a DefaultSessionCache
.
The DefaultSessionCacheFactory
has all of the same configuration setters as a DefaultSessionCache
.
Alternatively, if you only have a single SessionManager
, or you need to configure a DefaultSessionCache
differently for every SessionManager
, then you could dispense with the DefaultSessionCacheFactory
and simply instantiate, configure, and pass in the DefaultSessionCache
yourself.
Server server = new Server();
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
//EVICT_ON_INACTIVE: evict a session after 60sec inactivity
cacheFactory.setEvictionPolicy(60);
//Only useful with the EVICT_ON_INACTIVE policy
cacheFactory.setSaveOnInactiveEviction(true);
cacheFactory.setFlushOnResponseCommit(true);
cacheFactory.setInvalidateOnShutdown(false);
cacheFactory.setRemoveUnloadableSessions(true);
cacheFactory.setSaveOnCreate(true);
//Add the factory as a bean to the server, now whenever a
//SessionManager starts it will consult the bean to create a new DefaultSessionCache
server.addBean(cacheFactory);
If you don’t configure any SessionCache or SessionCacheFactory , a SessionManager will automatically create its own DefaultSessionCache .
|
The NullSessionCache
The NullSessionCache does not actually cache any objects: each request uses a fresh ManagedSession
object.
It is suitable for clustered deployments without a sticky load balancer and non-clustered deployments when purely minimal support for sessions is needed.
As no sessions are actually cached, of course functions like invalidateOnShutdown
and all of the eviction strategies have no meaning for the NullSessionCache
.
There is a NullSessionCacheFactory which you can instantiate, configure and set as a Server
bean to enable a SessionManager
to automatically create new NullSessionCache
s as needed.
All of the same configuration options are available on the NullSessionCacheFactory
as the NullSessionCache
itself.
Alternatively, if you only have a single SessionManager
, or you need to configure a NullSessionCache
differently for every SessionManager
, then you could dispense with the NullSessionCacheFactory
and simply instantiate, configure, and pass in the NullSessionCache
yourself.
Server server = new Server();
NullSessionCacheFactory cacheFactory = new NullSessionCacheFactory();
cacheFactory.setFlushOnResponseCommit(true);
cacheFactory.setRemoveUnloadableSessions(true);
cacheFactory.setSaveOnCreate(true);
//Add the factory as a bean to the server, now whenever a
//SessionManager starts it will consult the bean to create a new NullSessionCache
server.addBean(cacheFactory);
Implementing a custom SessionCache
As previously mentioned, it is strongly recommended that you extend the AbstractSessionCache.
Heterogeneous caching
Using one of the SessionCacheFactory
s will ensure that every time a SessionManager
starts it will create a new instance of the corresponding type of SessionCache
.
But, what if you deploy multiple webapps, and for one of them, you don’t want to use sessions?
Or alternatively, you don’t want to use sessions, but you have one webapp that now needs them?
In that case, you can configure the SessionCacheFactory
appropriate to the majority, and then specifically create the right type of SessionCache
for the others.
Here’s an example where we configure the DefaultSessionCacheFactory
to handle most webapps, but then specifically use a NullSessionCache
for another:
Server server = new Server();
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
//NEVER_EVICT
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
cacheFactory.setFlushOnResponseCommit(true);
cacheFactory.setInvalidateOnShutdown(false);
cacheFactory.setRemoveUnloadableSessions(true);
cacheFactory.setSaveOnCreate(true);
//Add the factory as a bean to the server, now whenever a
//SessionManager starts it will consult the bean to create a new DefaultSessionCache
server.addBean(cacheFactory);
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
//Add a webapp that will use a DefaultSessionCache via the DefaultSessionCacheFactory
WebAppContext app1 = new WebAppContext();
app1.setContextPath("/app1");
contexts.addHandler(app1);
//Add a webapp that uses an explicit NullSessionCache instead
WebAppContext app2 = new WebAppContext();
app2.setContextPath("/app2");
NullSessionCache nullSessionCache = new NullSessionCache(app2.getSessionHandler());
nullSessionCache.setFlushOnResponseCommit(true);
nullSessionCache.setRemoveUnloadableSessions(true);
nullSessionCache.setSaveOnCreate(true);
//If we pass an existing SessionCache instance to the SessionHandler, it must be
//fully configured: this means we must also provide SessionDataStore
nullSessionCache.setSessionDataStore(new NullSessionDataStore());
app2.getSessionHandler().setSessionCache(nullSessionCache);
The SessionDataStore
A SessionDataStore mediates the storage, retrieval and deletion of SessionData
.
There is one SessionDataStore
per SessionCache
and thus one per context.
Jetty provides a number of alternative SessionDataStore
implementations:
- NullSessionDataStore
-
Does not store
SessionData
, meaning that sessions will exist in-memory only. See NullSessionDataStore - FileSessionDataStore
-
Uses the file system to persist
SessionData
. See FileSessionDataStore for more information. - GCloudSessionDataStore
-
Uses GCloud Datastore for persisting
SessionData
. See GCloudSessionDataStore for more information. - HazelcastSessionDataStore
-
Uses Hazelcast for persisting
SessionData
. - InfinispanSessionDataStore
-
Uses Infinispan for persisting
SessionData
. See InfinispanSessionDataStore for more information. - JDBCSessionDataStore
-
Uses a relational database via JDBC API to persist
SessionData
. See JDBCSessionDataStore for more information. - MongoSessionDataStore
-
Uses MongoDB document database to persist
SessionData
. See MongoSessionDataStore for more information. - CachingSessionDataStore
-
Uses memcached to provide an L2 cache of
SessionData
while delegating to anotherSessionDataStore
for persistence ofSessionData
. See CachingSessionDataStore for more information.
Most of the behaviour common to SessionDataStore
s is provided by the AbstractSessionDataStore class.
You are strongly encouraged to use this as the base class for implementing your custom SessionDataStore
.
Some important methods are:
- isPassivating()
-
Boolean. "True" means that session data is serialized. Some persistence mechanisms serialize, such as JDBC, GCloud Datastore etc. Others can store an object in shared memory, e.g. Infinispan and thus don’t serialize session data. In Servlet environments, whether a
SessionDataStore
reports that it is capable of passivating controls whetherHttpSessionActivationListener
s will be called. When implementing a customSessionDataStore
you need to decide whether you will support passivation or not.
- setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
Custom SessionDataStores
When implementing a SessionDataStore
for a particular persistence technology, you should base it off the AbstractSessionDataStore
class.
Firstly, it is important to understand the components of a unique key for a session suitable for storing in a persistence mechanism. Consider that although multiple contexts may share the same session id (ie cross-context dispatch), the data in those sessions must be distinct. Therefore, when storing session data in a persistence mechanism that is shared by many nodes in a cluster, the session must be identified by a combination of the id and the context.
The SessionDataStore
s use the following information to synthesize a unique key for session data that is suitable to the particular persistence mechanism :
- id
-
This is the id as generated by the
SessionIdManager
- context
-
The path of the context associated with the session.
- virtual host
-
The first virtual host - if any - associated with the context.
The SessionContext class, of which every AbstractSessionDataStore
has an instance, will provide these components to you in a canonicalized form.
Then you will need to implement the following methods:
- public boolean doExists(String id)
-
Check if data for the given session exists in your persistence mechanism. The id is always relative to the context, see above.
- public void doStore(String id, SessionData data, long lastSaveTime)
-
Store the session data into your persistence mechanism. The id is always relative to the context, see above.
- public SessionData doLoad(String id)
-
Load the session from your persistent mechanism. The id is always relative to the context, see above.
- public Set<String> doCheckExpired(Set<String> candidates, long time)
-
Verify which of the suggested session ids have expired since the time given, according to the data stored in your persistence mechanism. This is used during scavenging to ensure that a session that is a candidate for expiry according to this node is not in-use on another node. The sessions matching these ids will be loaded as
ManagedSession
s and have their normal expiration lifecycle events invoked. The id is always relative to the context, see above. - public Set<String> doGetExpired(long before)
-
Find the ids of sessions that expired at or before the time given. The sessions matching these ids will be loaded as
ManagedSession
s and have their normal expiration lifecycle events invoked. The id is always relative to the context, see above. - public void doCleanOrphans(long time)
-
Find the ids of sessions that expired at or before the given time, independent of the context they are in. The purpose is to find sessions that are no longer being managed by any node. These sessions may even belong to contexts that no longer exist. Thus, any such sessions must be summarily deleted from the persistence mechanism and cannot have their normal expiration lifecycle events invoked.
The SessionDataStoreFactory
Every SessionDataStore
has a factory class that creates instances based on common configuration.
All SessionDataStoreFactory
implementations support configuring:
- setSavePeriodSec(int)
- setGracePeriodSec(int)
The NullSessionDataStore
The NullSessionDataStore
is a trivial implementation of SessionDataStore
that does not persist SessionData
.
Use it when you want your sessions to remain in memory only.
Be careful of your SessionCache
when using the NullSessionDataStore
:
-
if using a
NullSessionCache
then your sessions are neither shared nor saved -
if using a
DefaultSessionCache
with eviction settings, your session will cease to exist when it is evicted from the cache
If you have not configured any other SessionDataStore, when a SessionHandler
aka AbstractSessionManager
starts up, it will instantiate a NullSessionDataStore
.
The FileSessionDataStore
The FileSessionDataStore
supports persistent storage of session data in a filesystem.
Persisting sessions to the local file system should never be used in a clustered environment. |
One file represents one session in one context.
File names follow this pattern:
[expiry]_[contextpath]_[virtualhost]_[id]
- expiry
-
This is the expiry time in milliseconds since the epoch.
- contextpath
-
This is the context path with any special characters, including
/
, replaced by theunderscore character. For example, a context path of
/catalog
would become_catalog
. A context path of simply/
becomes just_
. - virtualhost
-
This is the first virtual host associated with the context and has the form of 4 digits separated by
.
characters. If there are no virtual hosts associated with a context, then0.0.0.0
is used:[digit].[digit].[digit].[digit]
- id
-
This is the unique id of the session.
Putting all of the above together as an example, a session with an id of node0ek3vx7x2y1e7pmi3z00uqj1k0
for the context with path /test
with no virtual hosts and an expiry of 1599558193150
would have a file name of:
1599558193150__test_0.0.0.0_node0ek3vx7x2y1e7pmi3z00uqj1k0
You can configure either a FileSessionDataStore individually, or a FileSessionDataStoreFactory
if you want multiple SessionHandler
s to use FileSessionDataStore
s that are identically configured.
The configuration methods are:
- setStoreDir(File) [Default:null]
-
This is the location for storage of session files. If the directory does not exist at startup, it will be created. If you use the same
storeDir
for multipleSessionHandlers
, then the sessions for all of those contexts are stored in the same directory. This is not a problem, as the name of the file is unique because it contains the context information. You must supply a value for this, otherwise startup of theFileSessionDataStore
will fail. - deleteUnrestorableFiles(boolean) [Default:false]
-
If set to
true
, unreadable files will be deleted. This is useful to prevent repeated logging of the same error when the scavenger periodically (re-)attempts to load the corrupted information for a session in order to expire it. - setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
Here’s an example of configuring a FileSessionDataStoreFactory
:
Server server = new Server();
//First lets configure a DefaultSessionCacheFactory
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
//NEVER_EVICT
cacheFactory.setEvictionPolicy(SessionCache.NEVER_EVICT);
cacheFactory.setFlushOnResponseCommit(true);
cacheFactory.setInvalidateOnShutdown(false);
cacheFactory.setRemoveUnloadableSessions(true);
cacheFactory.setSaveOnCreate(true);
//Add the factory as a bean to the server, now whenever a
//SessionManager starts it will consult the bean to create a new DefaultSessionCache
server.addBean(cacheFactory);
//Now, lets configure a FileSessionDataStoreFactory
FileSessionDataStoreFactory storeFactory = new FileSessionDataStoreFactory();
storeFactory.setStoreDir(new File("/tmp/sessions"));
storeFactory.setGracePeriodSec(3600);
storeFactory.setSavePeriodSec(0);
//Add the factory as a bean on the server, now whenever a
//SessionManager starts, it will consult the bean to create a new FileSessionDataStore
//for use by the DefaultSessionCache
server.addBean(storeFactory);
Here’s an alternate example, configuring a FileSessionDataStore
directly:
//create a context
WebAppContext app1 = new WebAppContext();
app1.setContextPath("/app1");
//First, we create a DefaultSessionCache
DefaultSessionCache cache = new DefaultSessionCache(app1.getSessionHandler());
cache.setEvictionPolicy(SessionCache.NEVER_EVICT);
cache.setFlushOnResponseCommit(true);
cache.setInvalidateOnShutdown(false);
cache.setRemoveUnloadableSessions(true);
cache.setSaveOnCreate(true);
//Now, we configure a FileSessionDataStore
FileSessionDataStore store = new FileSessionDataStore();
store.setStoreDir(new File("/tmp/sessions"));
store.setGracePeriodSec(3600);
store.setSavePeriodSec(0);
//Tell the cache to use the store
cache.setSessionDataStore(store);
//Tell the context to use the cache/store combination
app1.getSessionHandler().setSessionCache(cache);
The JDBCSessionDataStore
The JDBCSessionDataStore supports persistent storage of session data in a relational database.
To do that, it requires a DatabaseAdaptor
that handles the differences between databases (eg Oracle, Postgres etc), and a SessionTableSchema
that allows for the customization of table and column names.
The JDBCSessionDataStore and corresponding JDBCSessionDataStoreFactory support the following configuration:
- setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
- setDatabaseAdaptor(DatabaseAdaptor)
-
A
JDBCSessionDataStore
requires aDatabaseAdapter
, otherwise anException
is thrown at start time. - setSessionTableSchema(SessionTableSchema)
-
If a
SessionTableSchema
has not been explicitly set, one with all values defaulted is created at start time.
The DatabaseAdaptor
Many databases use different keywords for types such as long
, blob
and varchar
.
Jetty will detect the type of the database at runtime by interrogating the metadata associated with a database connection.
Based on that metadata Jetty will try to select that database’s preferred keywords.
However, you may need to instead explicitly configure these as described below.
- setDatasource(String)
- setDatasource(Datasource)
-
Either the JNDI name of a
Datasource
to look up, or theDatasource
itself. Alternatively you can set the driverInfo, see below.
DatabaseAdaptor datasourceAdaptor = new DatabaseAdaptor();
datasourceAdaptor.setDatasourceName("/jdbc/myDS");
- setDriverInfo(String, String)
- setDriverInfo(Driver, String)
-
This is the name or instance of a
Driver
class and a connection URL. Alternatively you can set the datasource, see above.
DatabaseAdaptor driverAdaptor = new DatabaseAdaptor();
driverAdaptor.setDriverInfo("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/sessions?user=sessionsadmin");
- setBlobType(String) [Default: "blob" or "bytea" for Postgres]
-
The type name used to represent "blobs" by the database.
- setLongType(String) [Default: "bigint" or "number(20)" for Oracle]
-
The type name used to represent large integers by the database.
- setStringType(String) [Default: "varchar"]
-
The type name used to represent character data by the database.
The SessionTableSchema
SessionData
is stored in a table with one row per session.
This is the definition of the table with the table name, column names, and type keywords all at their default settings:
sessionId | contextPath | virtualHost | lastNode | accessTime | lastAccessTime | createTime | cookieTime | lastSavedTime | expiryTime | maxInterval | map |
---|---|---|---|---|---|---|---|---|---|---|---|
120 varchar |
60 varchar |
60 varchar |
60 varchar |
long |
long |
long |
long |
long |
long |
long |
blob |
Use the SessionTableSchema
class to customize these names.
- setSchemaName(String), setCatalogName(String) [Default: null]
-
The exact meaning of these two are dependent on your database vendor, but can broadly be described as further scoping for the session table name. See https://en.wikipedia.org/wiki/Database_schema and https://en.wikipedia.org/wiki/Database_catalog. These extra scoping names come into play at startup time when Jetty determines if the session table already exists, or creates it on-the-fly. If your database is not using schema or catalog name scoping, leave these unset. If your database is configured with a schema or catalog name, use the special value "INFERRED" and Jetty will extract them from the database metadata. Alternatively, set them explicitly using these methods.
- setTableName(String) [Default:"JettySessions"]
-
This is the name of the table in which session data is stored.
- setAccessTimeColumn(String) [Default: "accessTime"]
-
This is the name of the column that stores the time - in ms since the epoch - at which a session was last accessed
- setContextPathColumn(String) [Default: "contextPath"]
-
This is the name of the column that stores the
contextPath
of a session. - setCookieTimeColumn(String) [Default: "cookieTime"]
-
This is the name of the column that stores the time - in ms since the epoch - that the cookie was last set for a session.
- setCreateTimeColumn(String) [Default: "createTime"]
-
This is the name of the column that stores the time - in ms since the epoch - at which a session was created.
- setExpiryTimeColumn(String) [Default: "expiryTime"]
-
This is name of the column that stores - in ms since the epoch - the time at which a session will expire.
- setLastAccessTimeColumn(String) [Default: "lastAccessTime"]
-
This is the name of the column that stores the time - in ms since the epoch - that a session was previously accessed.
- setLastSavedTimeColumn(String) [Default: "lastSavedTime"]
-
This is the name of the column that stores the time - in ms since the epoch - at which a session was last written.
- setIdColumn(String) [Default: "sessionId"]
-
This is the name of the column that stores the id of a session.
- setLastNodeColumn(String) [Default: "lastNode"]
-
This is the name of the column that stores the
workerName
of the last node to write a session. - setVirtualHostColumn(String) [Default: "virtualHost"]
-
This is the name of the column that stores the first virtual host of the context of a session.
- setMaxIntervalColumn(String) [Default: "maxInterval"]
-
This is the name of the column that stores the interval - in ms - during which a session can be idle before being considered expired.
- setMapColumn(String) [Default: "map"]
-
This is the name of the column that stores the serialized attributes of a session.
The MongoSessionDataStore
The MongoSessionDataStore
supports persistence of SessionData
in a nosql database.
The best description for the document model for session information is found in the javadoc for the MongoSessionDataStore. In overview, it can be represented thus:
The database contains a document collection for the sessions.
Each document represents a session id, and contains one nested document per context in which that session id is used.
For example, the session id abcd12345
might be used by two contexts, one with path /contextA
and one with path /contextB
.
In that case, the outermost document would refer to abcd12345
and it would have a nested document for /contextA
containing the session attributes for that context, and another nested document for /contextB
containing the session attributes for that context.
Remember, according to the Servlet Specification, a session id can be shared by many contexts, but the attributes must be unique per context.
The outermost document contains these fields:
- id
-
The session id.
- created
-
The time (in ms since the epoch) at which the session was first created in any context.
- maxIdle
-
The time (in ms) for which an idle session is regarded as valid. As maxIdle times can be different for
Session
s from different contexts, this is the shortest maxIdle time. - expiry
-
The time (in ms since the epoch) at which the session will expire. As the expiry time can be different for
Session
s from different contexts, this is the shortest expiry time.
Each nested context-specific document contains:
- attributes
-
The session attributes as a serialized map.
- lastSaved
-
The time (in ms since the epoch) at which the session in this context was saved.
- lastAccessed
-
The time (in ms since the epoch) at which the session in this context was previously accessed.
- accessed
-
The time (in ms since the epoch) at which this session was most recently accessed.
- lastNode
-
The workerName of the last server that saved the session data.
- version
-
An object that is updated every time a session is written for a context.
You can configure either a MongoSessionDataStore individually, or a MongoSessionDataStoreFactory if you want multiple SessionHandler
s to use MongoSessionDataStore
s that are identically configured.
The configuration methods for the MongoSessionDataStoreFactory
are:
- setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
- setDbName(String)
-
This is the name of the database.
- setCollectionName(String)
-
The name of the document collection.
- setConnectionString(String)
-
a mongodb url, eg "mongodb://localhost". Alternatively, you can specify the host,port combination instead, see below.
- setHost(String)
- setPort(int)
-
the hostname and port number of the mongodb instance to contact. Alternatively, you can specify the connectionString instead, see above.
This is an example of configuring a MongoSessionDataStoreFactory
:
Server server = new Server();
MongoSessionDataStoreFactory mongoSessionDataStoreFactory = new MongoSessionDataStoreFactory();
mongoSessionDataStoreFactory.setGracePeriodSec(3600);
mongoSessionDataStoreFactory.setSavePeriodSec(0);
mongoSessionDataStoreFactory.setDbName("HttpSessions");
mongoSessionDataStoreFactory.setCollectionName("JettySessions");
// Either set the connectionString
mongoSessionDataStoreFactory.setConnectionString("mongodb:://localhost:27017");
// or alternatively set the host and port.
mongoSessionDataStoreFactory.setHost("localhost");
mongoSessionDataStoreFactory.setPort(27017);
The InfinispanSessionDataStore
The InfinispanSessionDataStore
supports persistent storage of session data via the Infinispan data grid.
You may use Infinispan in either embedded mode, where it runs in the same process as Jetty, or in remote mode mode, where your Infinispan instance is on another node.
For more information on Infinispan, including some code examples, consult the Infinispan documentation.
See below for some code examples of configuring the InfinispanSessionDataStore in Jetty.
Note that the configuration options are the same for both the InfinispanSessionDataStore
and the InfinispanSessionDataStoreFactory.
Use the latter to apply the same configuration to multiple InfinispanSessionDataStore
s.
- setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
- setCache(BasicCache<String, InfinispanSessionData> cache)
-
Infinispan uses a cache API as the interface to the data grid and this method configures Jetty with the cache instance. This cache can be either an embedded cache - also called a "local" cache in Infinispan parlance - or a remote cache.
- setSerialization(boolean) [Default: false]
-
When the
InfinispanSessionDataStore
starts, if it detects the Infinispan classes for remote caches on the classpath, it will automatically assumeserialization
is true, and thus thatSessionData
will be serialized over-the-wire to a remote cache. You can use this parameter to override this. If this parameter istrue
, theInfinispanSessionDataStore
returns true for theisPassivating()
method, but false otherwise. - setInfinispanIdleTimeoutSec(int) [Default: 0]
-
This controls the Infinispan option whereby it can detect and delete entries that have not been referenced for a configurable amount of time. A value of 0 disables it.
If you use this option, expired sessions will be summarily deleted from Infinispan without the normal session invalidation handling (eg calling of lifecycle listeners). Only use this option if you do not have session lifecycle listeners that must be called when a session is invalidated. |
- setQueryManager(QueryManager)
-
If this parameter is not set, the
InfinispanSessionDataStore
will be unable to scavenge for unused sessions. In that case, you can use theinfinispanIdleTimeoutSec
option instead to prevent the accumulation of expired sessions. When using Infinispan in embedded mode, configure the EmbeddedQueryManager to enable Jetty to query for expired sessions so that they may be property invalidated and lifecycle listeners called. When using Infinispan in remote mode, configure the RemoteQueryManager instead.
Here is an example of configuring an InfinispanSessionDataStore
in code using an embedded cache:
/* Create a core SessionHandler
* Alternatively in a Servlet Environment do:
* WebAppContext webapp = new WebAppContext();
* SessionHandler sessionHandler = webapp.getSessionHandler();
*/
SessionHandler sessionHandler = new SessionHandler();
//Use an Infinispan local cache configured via an infinispan xml file
DefaultCacheManager defaultCacheManager = new DefaultCacheManager("path/to/infinispan.xml");
Cache<String, InfinispanSessionData> localCache = defaultCacheManager.getCache();
//Configure the Jetty session datastore with Infinispan
InfinispanSessionDataStore infinispanSessionDataStore = new InfinispanSessionDataStore();
infinispanSessionDataStore.setCache(localCache);
infinispanSessionDataStore.setSerialization(false); //local cache does not serialize session data
infinispanSessionDataStore.setInfinispanIdleTimeoutSec(0); //do not use infinispan auto delete of unused sessions
infinispanSessionDataStore.setQueryManager(new org.eclipse.jetty.session.infinispan.EmbeddedQueryManager(localCache)); //enable Jetty session scavenging
infinispanSessionDataStore.setGracePeriodSec(3600);
infinispanSessionDataStore.setSavePeriodSec(0);
//Configure a SessionHandler to use the local Infinispan cache as a store of SessionData
DefaultSessionCache sessionCache = new DefaultSessionCache(sessionHandler);
sessionCache.setSessionDataStore(infinispanSessionDataStore);
sessionHandler.setSessionCache(sessionCache);
Here is an example of configuring an InfinispanSessionDataStore
in code using a remote cache:
/* Create a core SessionHandler
* Alternatively in a Servlet Environment do:
* WebAppContext webapp = new WebAppContext();
* SessionHandler sessionHandler = webapp.getSessionHandler();
*/
SessionHandler sessionHandler = new SessionHandler();
//Configure Infinispan to provide a remote cache called "JettySessions"
Properties hotrodProperties = new Properties();
hotrodProperties.load(new FileInputStream("/path/to/hotrod-client.properties"));
org.infinispan.client.hotrod.configuration.ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.withProperties(hotrodProperties);
configurationBuilder.marshaller(new ProtoStreamMarshaller());
configurationBuilder.addContextInitializer(new org.eclipse.jetty.session.infinispan.InfinispanSerializationContextInitializer());
org.infinispan.client.hotrod.RemoteCacheManager remoteCacheManager = new RemoteCacheManager(configurationBuilder.build());
RemoteCache<String, InfinispanSessionData> remoteCache = remoteCacheManager.getCache("JettySessions");
//Configure the Jetty session datastore with Infinispan
InfinispanSessionDataStore infinispanSessionDataStore = new InfinispanSessionDataStore();
infinispanSessionDataStore.setCache(remoteCache);
infinispanSessionDataStore.setSerialization(true); //remote cache serializes session data
infinispanSessionDataStore.setInfinispanIdleTimeoutSec(0); //do not use infinispan auto delete of unused sessions
infinispanSessionDataStore.setQueryManager(new org.eclipse.jetty.session.infinispan.RemoteQueryManager(remoteCache)); //enable Jetty session scavenging
infinispanSessionDataStore.setGracePeriodSec(3600);
infinispanSessionDataStore.setSavePeriodSec(0);
//Configure a SessionHandler to use a remote Infinispan cache as a store of SessionData
DefaultSessionCache sessionCache = new DefaultSessionCache(sessionHandler);
sessionCache.setSessionDataStore(infinispanSessionDataStore);
sessionHandler.setSessionCache(sessionCache);
The GCloudSessionDataStore
The GCloudSessionDataStore
supports persistent storage of session data into Google Cloud DataStore.
Preparation
You will first need to create a project and enable the Google Cloud API: https://cloud.google.com/docs/authentication#preparation.
Take note of the project id
that you create in this step as you need to supply it in later steps.
You can choose to use Jetty either inside or outside of Google infrastructure.
-
Outside of Google infrastructure
Before running Jetty, you will need to choose one of the following methods to set up the local environment to enable remote GCloud DataStore communications:
-
Using the GCloud SDK
-
Ensure you have the GCloud SDK installed: https://cloud.google.com/sdk/?hl=en
-
Use the GCloud tool to set up the project you created in the preparation step:
gcloud config set project PROJECT_ID
-
Use the GCloud tool to authenticate a Google account associated with the project created in the preparation step:
gcloud auth login ACCOUNT
-
-
Using environment variables
-
Define the environment variable
GCLOUD_PROJECT
with the project id you created in the preparation step. -
Generate a JSON service account key and then define the environment variable
GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/key.json
-
-
-
Inside of Google infrastructure
The Google deployment tools will automatically configure the project and authentication information for you.
Jetty GCloud session support provides some indexes as optimizations that can speed up session searches.
This will particularly benefit session scavenging, although it may make write operations slower.
By default, indexes will not be used.
You will see a log WARNING
message informing you about the absence of indexes:
WARN: Session indexes not uploaded, falling back to less efficient queries
In order to use them, you will need to manually upload the file to GCloud that defines the indexes.
This file is named index.yaml
and you can find it in your distribution in $JETTY_BASE/etc/sessions/gcloud/index.yaml
.
Follow the instructions here to upload the pre-generated index.yaml
file.
Configuration
The following configuration options apply to both the GCloudSessionDataStore and the GCloudSessionDataStoreFactory.
Use the latter if you want multiple SessionHandler
s to use GCloudSessionDataStore
s that are identically configured.
- setSavePeriodSec(int) [Default:0]
-
This is an interval defined in seconds. It is used to reduce the frequency with which
SessionData
is written. Normally, whenever the last concurrent request leaves aSession
, theSessionData
for thatSession
is always persisted, even if the only thing that changed is thelastAccessTime
. If thesavePeriodSec
is non-zero, theSessionData
will not be persisted if no session attributes changed, unless the time since the last save exceeds thesavePeriod
. Setting a non-zero value can reduce the load on the persistence mechanism, but in a clustered environment runs the risk that other nodes will see the session as expired because it has not been persisted sufficiently recently. - setGracePeriodSec(int) [Default:3600]
-
The
gracePeriod
is an interval defined in seconds. It is an attempt to deal with the non-transactional nature of sessions with regard to finding sessions that have expired. In a clustered configuration - even with a sticky load balancer - it is always possible that a session is "live" on a node but not yet updated in the persistent store. This means that it can be hard to determine at any given moment whether a clustered session has truly expired. Thus, we use thegracePeriod
to provide a bit of leeway around the moment of expiry during scavenging:-
on every scavenge cycle an
AbstractSessionDataStore
searches for sessions that belong to the context that expired at least onegracePeriod
ago -
infrequently the
AbstractSessionDataStore
searches for and summarily deletes sessions - from any context - that expired at least 10gracePeriod
s ago
-
- setProjectId(String) [Default: null]
-
Optional. The
project id
of your project. You don’t need to set this if you carried out the instructions in the Preparation section, but you might want to set this - along with thehost
and/ornamespace
parameters - if you want more explicit control over connecting to GCloud. - setHost(String) [Default: null]
-
Optional. This is the name of the host for the GCloud DataStore. If you leave it unset, then the GCloud DataStore library will work out the host to contact. You might want to use this - along with
projectId
and/ornamespace
parameters - if you want more explicit control over connecting to GCloud. - setNamespace(String) [Default: null]
-
Optional. If set, partitions the visibility of session data in multi-tenant deployments. More information can be found here.
- setMaxRetries(int) [Default: 5]
-
This is the maximum number of retries to connect to GCloud DataStore in order to write a session. This is used in conjunction with the
backoffMs
parameter to control the frequency with which Jetty will retry to contact GCloud to write out a session. - setBackoffMs(int) [Default: 1000]
-
This is the interval that Jetty will wait in between retrying failed writes. Each time a write fails, Jetty doubles the previous backoff. Used in conjunction with the
maxRetries
parameter. - setEntityDataModel(EntityDataModel)
-
The
EntityDataModel
encapsulates the type (called "kind" in GCloud DataStore) of stored session objects and the names of its fields. If you do not set this parameter,GCloudSessionDataStore
uses all default values, which should be sufficient for most needs. Should you need to customize this, the methods and their defaults are:-
setKind(String) [Default: "GCloudSession"] this is the type of the session object.
-
setId(String) [Default: "id"] this is the name of the field storing the session id.
-
setContextPath(String) [Default: "contextPath"] this is name of the field storing the canonicalized context path of the context to which the session belongs.
-
setVhost(String) [Default: "vhost"] this the name of the field storing the canonicalized virtual host of the context to which the session belongs.
-
setAccessed(String) [Default: "accessed"] this is the name of the field storing the current access time of the session.
-
setLastAccessed(String) [Default: "lastAccessed"] this is the name of the field storing the last access time of the session.
-
setCreateTime(String) [Default: "createTime"] this is the name of the field storing the time in ms since the epoch, at which the session was created.
-
setCookieSetTime(String) [Default: "cookieSetTime"] this is the name of the field storing time at which the session cookie was last set.
-
setLastNode(String) [Default: "lastNode"] this is the name of the field storing the
workerName
of the last node to manage the session. -
setExpiry(String) [Default: "expiry"] this is the name of the field storing the time, in ms since the epoch, at which the session will expire.
-
setMaxInactive(String) [Default: "maxInactive"] this is the name of the field storing the session timeout in ms.
-
setAttributes(String) [Default: "attributes"] this is the name of the field storing the session attribute map.
-
Here’s an example of configuring a GCloudSessionDataStoreFactory
:
Server server = new Server();
//Ensure there is a SessionCacheFactory
DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
//Add the factory as a bean to the server, now whenever a
//SessionManager starts it will consult the bean to create a new DefaultSessionCache
server.addBean(cacheFactory);
//Configure the GCloudSessionDataStoreFactory
GCloudSessionDataStoreFactory storeFactory = new GCloudSessionDataStoreFactory();
storeFactory.setGracePeriodSec(3600);
storeFactory.setSavePeriodSec(0);
storeFactory.setBackoffMs(2000); //increase the time between retries of failed writes
storeFactory.setMaxRetries(10); //increase the number of retries of failed writes
//Add the factory as a bean on the server, now whenever a
//SessionManager starts, it will consult the bean to create a new GCloudSessionDataStore
//for use by the DefaultSessionCache
server.addBean(storeFactory);
The CachingSessionDataStore
The CachingSessionDataStore is a special type of SessionDataStore
that checks an L2 cache for SessionData
before checking a delegate SessionDataStore
.
This can improve the performance of slow stores.
The L2 cache is an instance of a SessionDataMap.
Jetty provides one implementation of this L2 cache based on memcached
, MemcachedSessionDataMap.
This is an example of how to programmatically configure CachingSessionDataStore
s, using a FileSessionDataStore as a delegate, and memcached
as the L2 cache:
Server server = new Server();
//Make a factory for memcached L2 caches for SessionData
MemcachedSessionDataMapFactory mapFactory = new MemcachedSessionDataMapFactory();
mapFactory.setExpirySec(0); //items in memcached don't expire
mapFactory.setHeartbeats(true); //tell memcached to use heartbeats
mapFactory.setAddresses(new InetSocketAddress("localhost", 11211)); //use a local memcached instance
mapFactory.setWeights(new int[]{100}); //set the weighting
//Make a FileSessionDataStoreFactory for creating FileSessionDataStores
//to persist the session data
FileSessionDataStoreFactory storeFactory = new FileSessionDataStoreFactory();
storeFactory.setStoreDir(new File("/tmp/sessions"));
storeFactory.setGracePeriodSec(3600);
storeFactory.setSavePeriodSec(0);
//Make a factory that plugs the L2 cache into the SessionDataStore
CachingSessionDataStoreFactory cachingSessionDataStoreFactory = new CachingSessionDataStoreFactory();
cachingSessionDataStoreFactory.setSessionDataMapFactory(mapFactory);
cachingSessionDataStoreFactory.setSessionStoreFactory(storeFactory);
//Register it as a bean so that all SessionManagers will use it
//to make FileSessionDataStores that use memcached as an L2 SessionData cache.
server.addBean(cachingSessionDataStoreFactory);