Update session documentation.
This commit is contained in:
parent
7a6404d9fd
commit
b4333c2a24
|
@ -63,7 +63,7 @@ include::connectors/chapter.adoc[]
|
|||
include::http2/chapter.adoc[]
|
||||
include::logging/chapter.adoc[]
|
||||
include::security/chapter.adoc[]
|
||||
include::sessions/chapter.adoc[]
|
||||
include::sessions/sessions.adoc[]
|
||||
include::jsp/chapter.adoc[]
|
||||
include::annotations/chapter.adoc[]
|
||||
include::jmx/chapter.adoc[]
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-management]]
|
||||
== 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.
|
||||
Choosing the correct session manager implementation is an important consideration for every application as each can fit and perform optimally in different situations.
|
||||
If you need a simple in-memory session manager that can persist to disk then session management using the local file system can be a good place to start.
|
||||
If you need a session manager that can work in a clustered scenario with multiple instances of Jetty, then the JDBC session manager can be an excellent option.
|
||||
Jetty also offers more niche session managers that leverage backends such as MongoDB, Inifinispan, or even Google's Cloud Data Store.
|
||||
|
||||
include::session-hierarchy.adoc[]
|
||||
include::sessions-details.adoc[]
|
||||
include::session-configuration-housekeeper.adoc[]
|
||||
include::session-configuration-sessioncache.adoc[]
|
||||
include::session-configuration-memory.adoc[]
|
||||
include::session-configuration-file-system.adoc[]
|
||||
include::session-configuration-jdbc.adoc[]
|
||||
include::session-configuration-mongodb.adoc[]
|
||||
include::session-configuration-infinispan.adoc[]
|
||||
include::session-configuration-hazelcast.adoc[]
|
||||
include::session-configuration-gcloud.adoc[]
|
||||
include::session-configuration-memcachedsessiondatastore.adoc[]
|
||||
include::sessions-usecases.adoc[]
|
||||
//include::setting-session-characteristics.adoc[]
|
||||
//include::using-persistent-sessions.adoc[]
|
||||
//include::session-clustering-jdbc.adoc[]
|
||||
//include::session-clustering-mongodb.adoc[]
|
||||
//include::session-clustering-infinispan.adoc[]
|
||||
//include::session-clustering-gcloud-datastore.adoc[]
|
|
@ -1,276 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-clustering-gcloud-datastore]]
|
||||
=== Session Clustering with Google Cloud Datastore
|
||||
|
||||
Jetty can support session clustering by persisting sessions to https://cloud.google.com/datastore/docs/concepts/overview[Google Cloud Datastore].
|
||||
Each Jetty instance locally caches sessions for which it has received requests, writing any changes to the session through to the Datastore as the request exits the server.
|
||||
Sessions must obey the Serialization contract, and servlets must call the `Session.setAttribute()` method to ensure that changes are persisted.
|
||||
|
||||
The persistent session mechanism works in conjunction with a load balancer that supports stickiness.
|
||||
Stickiness can be based on various data items, such as source IP address or characteristics of the session ID or a load-balancer specific mechanism.
|
||||
For those load balancers that examine the session ID, the Jetty persistent session mechanism appends a node ID to the session ID, which can be used for routing.
|
||||
|
||||
==== Configuration
|
||||
|
||||
There are two components to session management in Jetty: a session ID manager and a session manager.
|
||||
|
||||
- The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there can only be one session ID manager per Jetty instance.
|
||||
- The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.
|
||||
|
||||
These managers also cooperate and collaborate with the `org.eclipse.jetty.server.session.SessionHandler` to enable cross-context dispatch.
|
||||
|
||||
==== The gcloud-sessions Module
|
||||
|
||||
When using the jetty distribution, to enable Cloud Datastore session persistence, you will first need to enable the `gcloud-sessions` link:#startup-modules[module] for your link:#creating-jetty-base[base] using the `--add-to-start` argument to the link:#startup-overview[start.jar].
|
||||
|
||||
As part of the module installation, the necessary jars will be dynamically downloaded and installed to your `${jetty.base}/lib/gcloud` directory.
|
||||
If you need to up or downgrade the version of the 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=glcoud-sessions` 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.
|
||||
|
||||
===== Configuring the GCloudSessionIdManager
|
||||
|
||||
The gcloud-sessions module will have installed file called `${jetty.home}/etc/jetty-gcloud-sessions.xml`.
|
||||
This file configures an instance of the `GCloudSessionIdManager` that will be shared across all webapps deployed on that server. It looks like this:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
include::{SRCDIR}/jetty-gcloud/jetty-gcloud-session-manager/src/main/config/etc/jetty-gcloud-sessions.xml[]
|
||||
----
|
||||
|
||||
You configure it by setting values for properties.
|
||||
The properties will either be inserted as commented out in your `start.ini`, or your `start.d/gcloud-sessions.ini` file, depending on how you enabled the module.
|
||||
|
||||
The only property you always need to set is the name of the node in the cluster:
|
||||
|
||||
jetty.gcloudSession.workerName::
|
||||
The name that uniquely identifies this node in the cluster.
|
||||
This value will also be used by the sticky load balancer to identify the node.
|
||||
Don't forget to change the value of this property on *each* node on which you enable gcloud datastore session clustering.
|
||||
|
||||
|
||||
===== Configuring GCloud Datastore
|
||||
|
||||
Things that you will need:
|
||||
|
||||
- a local installation of the https://cloud.google.com/sdk/[Google Cloud SDK]
|
||||
- a project id referred to below as [YOUR PROJECT ID]
|
||||
- to have https://cloud.google.com/datastore/docs/activate[enabled your project id] to use GCloud Datastore
|
||||
|
||||
====== Using GCloud Datastore from Compute/AppEngine
|
||||
|
||||
If you are running your webapp from within ComputeEngine or AppEngine, you do not need to do anything else in order to configure your GCloud setup. All necessary information will be inferred from the environment by the infrastrcture.
|
||||
|
||||
====== Using GCloud Datastore from an external server
|
||||
|
||||
If you are running your webapp externally to Google infrastructure, you can still interact with the remote GCloud Datastore service.
|
||||
|
||||
Execute the following commands:
|
||||
|
||||
- gcloud config set project [YOUR PROJECT ID].
|
||||
- gcloud auth login
|
||||
|
||||
This will populate your environment with the necessary authentication information to allow you to contact the remote GCloud Datastore instance.
|
||||
|
||||
====== Using GCloud Datastore local development server
|
||||
|
||||
If you would like to locally test your application, you can use the Google Cloud SDK's https://cloud.google.com/datastore/docs/tools/datastore-emulator[GCloud Datastore emulator].
|
||||
|
||||
Follow the instructions on the https://cloud.google.com/datastore/docs/tools/datastore-emulator[GCloud Datastore emulator page] to set up your environment.
|
||||
|
||||
===== Configuring the GCloudSessionManager
|
||||
|
||||
As mentioned elsewhere, there must be one `SessionManager` per context (e.g. webapp).
|
||||
Each SessionManager needs to reference the single `GCloudSessionIdManager`.
|
||||
|
||||
The way you configure a `GCloudSessionManager` depends on whether you're configuring from a context xml file, a `jetty-web.xml` file or code.
|
||||
The basic difference is how you get a reference to the Jetty `org.eclipse.jetty.server.Server` instance.
|
||||
|
||||
From a context xml file, you reference the Server instance as a Ref:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Get a reference to the GCloudSessionIdManager -->
|
||||
<Ref id="Server">
|
||||
<Call id="idMgr" name="getSessionIdManager"/>
|
||||
</Ref>
|
||||
|
||||
<!-- Use the GCloudSessionIdManager to set up the GCloudSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.gcloud.session.GCloudSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="scavengeIntervalSec">600</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance directly:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Reference the server directly -->
|
||||
<Get name="server">
|
||||
<Get id="idMgr" name="sessionIdManager"/>
|
||||
</Get>
|
||||
|
||||
<!-- Apply the SessionIdManager to the GCloudSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.gcloud.session.GCloudSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="scavengeIntervalSec">600</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
The `GCloudSessionManager` supports the following configuration setters:
|
||||
|
||||
scavengeIntervalSec::
|
||||
Time in seconds between runs of a scavenger task that looks for expired old sessions to delete.
|
||||
The default is 10 minutes.
|
||||
If set to 0, no scavenging is done.
|
||||
staleIntervalSec::
|
||||
The length of time a session can be in memory without being checked against the cluster.
|
||||
A value of 0 indicates that the session is never checked against the cluster - the current node is considered to be the master for the session.
|
||||
maxQueryResults::
|
||||
The maximum number of results to return for a query to find expired sessions.
|
||||
For efficiency it is important to limit the size of the result.
|
||||
The default is 100.
|
||||
If 0 or negative numbers are set, the default is used instead.
|
||||
|
||||
===== The gcloud-memcached-sessions module
|
||||
|
||||
As an optimization, you can have Jetty store your session data into GCloud Datastore but also cache it into memcached. This serves two purposes: faster read-accesses and also better support for non-sticky load balancers (although using a non-sticky load balancer is highly undesirable and not recommended).
|
||||
|
||||
You will need to enable the `gcloud-memcached-sessions` link:#startup-modules[module] for your link:#creating-jetty-base[base] using the `--add-to-start` argument to the link:#startup-overview[start.jar].
|
||||
|
||||
If you already enabled the gcloud-sessions module, that's fine as the gcloud-memcached-sessions module depends on it anyway.
|
||||
|
||||
Jetty uses the https://github.com/killme2008/xmemcached[Xmemcached] java client.
|
||||
It depends on http://www.slf4j.org/[slf4j], so you will need to choose an http://www.slf4j.org/[slf4j logging implementation]. You can copy the chosen implementation jars into your $jetty.base/lib/ext directory.
|
||||
|
||||
====== Configuring the GCloudSessionIdManager
|
||||
|
||||
The instructions here are exactly the same as for the gcloud-sessions module.
|
||||
|
||||
====== Configuring GCloud Datastore
|
||||
|
||||
The instructions here are exactly the same as for the gcloud-sessions module.
|
||||
|
||||
====== Configuring Memcached
|
||||
|
||||
If you have installed memcached on a host and port other than the defaults of `localhost` and `11211`, then you will need to take note of these values and supply them to the configuration of the `GCloudMemcachedSessionManager`.
|
||||
|
||||
====== Configuring the GCloudMemcachedSessionManager
|
||||
|
||||
*Note that* you will be configuring a `GCloudMemcachedSessionManager` 'instead of' a `GCloudSessionManager`.
|
||||
|
||||
As usual, there must be only one per context (e.g. webapp).
|
||||
Each GCloudMemcachedSessionManager needs to reference the single `GCloudSessionIdManager`.
|
||||
|
||||
|
||||
The way you configure a `GCloudMemcachedSessionManager` depends on whether you're configuring from a context xml file, a `jetty-web.xml` file or code.
|
||||
The basic difference is how you get a reference to the Jetty `org.eclipse.jetty.server.Server` instance.
|
||||
|
||||
From a context xml file, you reference the Server instance as a Ref:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Get a reference to the GCloudSessionIdManager -->
|
||||
<Ref id="Server">
|
||||
<Call id="idMgr" name="getSessionIdManager"/>
|
||||
</Ref>
|
||||
|
||||
<!-- Use the GCloudSessionIdManager to set up the GCloudMemcachedSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.gcloud.memcached.session.GCloudMemcachedSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="scavengeIntervalSec">600</Set>
|
||||
<Set name="host">myhost</Set>
|
||||
<Set name="port">11211</Set>
|
||||
<Set name="expirySec">0</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance directly:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Reference the server directly -->
|
||||
<Get name="server">
|
||||
<Get id="idMgr" name="sessionIdManager"/>
|
||||
</Get>
|
||||
|
||||
<!-- Apply the SessionIdManager to the GCloudMemcachedSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.gcloud..memcached.session.GCloudMemcachedSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="scavengeIntervalSec">600</Set>
|
||||
<Set name="host">myhost</Set>
|
||||
<Set name="port">11211</Set>
|
||||
<Set name="expirySec">0</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
The `GCloudMemcachedSessionManager` supports the following configuration setters:
|
||||
|
||||
scavengeIntervalSec::
|
||||
Time in seconds between runs of a scavenger task that looks for expired old sessions to delete.
|
||||
The default is 10 minutes.
|
||||
If set to 0, no scavenging is done.
|
||||
staleIntervalSec::
|
||||
The length of time a session can be in memory without being checked against the cluster.
|
||||
A value of 0 indicates that the session is never checked against the cluster - the current node is considered to be the master for the session.
|
||||
maxQueryResults::
|
||||
The maximum number of results to return for a query to find expired sessions.
|
||||
For efficiency it is important to limit the size of the result.
|
||||
The default is 100.
|
||||
If 0 or negative numbers are set, the default is used instead.
|
||||
host::
|
||||
The address of the host where the memcached server is running. Defaults to "localhost".
|
||||
port::
|
||||
The port on the host where the memcached serer is running. Defaults to "11211".
|
||||
expirySec::
|
||||
The time in seconds that an entry in the memcached cache is considered valid. By default, entries are are not aged out of the cached, however they may be evicted due to memory constraints.
|
|
@ -1,192 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-clustering-infinispan]]
|
||||
=== Session Clustering with Infinispan
|
||||
|
||||
Jetty can support session clustering by persisting sessions to http://www.infinispan.org[Infinispan].
|
||||
Each Jetty instance locally caches sessions for which it has received requests, writing any changes to the session through to Infinispan as the request exits the server.
|
||||
Sessions must obey the Serialization contract, and servlets must call the `Session.setAttribute()` method to ensure that changes are persisted.
|
||||
|
||||
The persistent session mechanism works in conjunction with a load balancer that supports stickiness.
|
||||
Stickiness can be based on various data items, such as source IP address or characteristics of the session ID or a load-balancer specific mechanism.
|
||||
For those load balancers that examine the session ID, the Jetty persistent session mechanism appends a node ID to the session ID, which can be used for routing.
|
||||
|
||||
==== Configuration
|
||||
|
||||
There are two components to session management in Jetty: a session ID manager and a session manager.
|
||||
|
||||
* The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there can only be one session ID manager per Jetty instance.
|
||||
* The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.
|
||||
|
||||
These managers also cooperate and collaborate with the `org.eclipse.jetty.server.session.SessionHandler` to enable cross-context dispatch.
|
||||
|
||||
==== The Infinispan Module
|
||||
|
||||
When using the jetty distribution, to enable Infinispan session persistence, you will first need to enable the Infinispan link:#startup-modules[module] for your link:#creating-jetty-base[base] using the `--add-to-start` argument to the link:#startup-overview[start.jar].
|
||||
|
||||
As part of the module installation, the necessary Infinispan jars will be dynamically downloaded and installed to your `${jetty.base}/lib/infinispan` directory.
|
||||
If you need to up or downgrade the version of the Infinispan 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=infinispan` 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/infinispan.ini` file or appended to your `start.ini`, depending on how you enabled the module:
|
||||
|
||||
....
|
||||
## Unique identifier for this node in the cluster
|
||||
jetty.infinispanSession.workerName=node1
|
||||
....
|
||||
|
||||
jetty.infinispanSession.workerName::
|
||||
The name that uniquely identifies this node in the cluster.
|
||||
This value will also be used by the sticky load balancer to identify the node.
|
||||
Don't forget to change the value of this property on *each* node on which you enable Infinispan session clustering.
|
||||
|
||||
These properties are applied to the `InfinispanSessionIdManager` described below.
|
||||
|
||||
===== Configuring the InfinispanSessionIdManager
|
||||
|
||||
The Infinispan module will have installed file called `$\{jetty.home}/etc/jetty-infinispan.xml`.
|
||||
This file configures an instance of the `InfinispanSessionIdManager` that will be shared across all webapps deployed on that server.
|
||||
It looks like this:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
include::{SRCDIR}/jetty-infinispan/src/main/config/etc/jetty-infinispan.xml[]
|
||||
----
|
||||
|
||||
As you can see, you configure the Infinispan http://infinispan.org/docs/7.1.x/user_guide/user_guide.html#_the_cache_apis[Cache] instance that the `InfinispanSessionIdManager` should use in this file.
|
||||
By default, the Infinispan http://infinispan.org/docs/7.1.x/getting_started/getting_started.html#_running_infinispan_on_a_single_node[Default cache] instance is used (e.g. on the local node).
|
||||
You can instead use a custom Cache setup - the `jetty-infinispan.xml` file shows you how to configure a remote Cache (using the http://infinispan.org/docs/7.1.x/user_guide/user_guide.html#_using_hot_rod_server[hotrod java client]).
|
||||
|
||||
The `InfinispanSessionIdManager` can be configured by calling setters:
|
||||
|
||||
idleExpiryMultiple::
|
||||
Sessions that are not immortal, e.g. they have an expiry time, have their ids stored into Infinispan with an http://infinispan.org/docs/7.1.x/user_guide/user_guide.html#_expiration[idle expiry timeout] equivalent to double the session's timeout.
|
||||
This should be sufficient to ensure that a session id that is in-use by a session is never accidentally removed.
|
||||
However, should you wish to, you can configure this to any integral value to effectively increase the http://infinispan.org/docs/7.1.x/user_guide/user_guide.html#_expiration[idle expiry] timeout.
|
||||
|
||||
===== Configuring the InfinispanSessionManager
|
||||
|
||||
As mentioned elsewhere, there should be one `InfinispanSessionManager` per context (e.g. webapp).
|
||||
It will need to reference the single `InfinispanSessionIdManager` configured previously for the Server.
|
||||
|
||||
The way you configure a `InfinispanSessionManager` depends on whether you're configuring from a context xml file, a `jetty-web.xml` file or code.
|
||||
The basic difference is how you get a reference to the Jetty `org.eclipse.jetty.server.Server` instance.
|
||||
|
||||
From a context xml file, you reference the Server instance as a Ref:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Expose the jetty infinispan classes for session serialization -->
|
||||
<Get name="serverClasspathPattern">
|
||||
<Call name="add">
|
||||
<Arg>-org.eclipse.jetty.session.infinispan.</Arg>
|
||||
</Call>
|
||||
</Get>
|
||||
|
||||
|
||||
<!-- Get a reference to the InfinispanSessionIdManager -->
|
||||
<Ref id="Server">
|
||||
<Call id="idMgr" name="getSessionIdManager"/>
|
||||
</Ref>
|
||||
|
||||
<!-- Get a referencee to the Cache from the InfinispanSessionIdManager -->
|
||||
<Ref id="idMgr">
|
||||
<Get id="cache" name="cache"/>
|
||||
</Ref>
|
||||
|
||||
<!-- Use the InfinispanSessionIdManager and Cache to setup up the InfinispanSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.session.infinispan.InfinispanSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="cache">
|
||||
<Ref id="cache">
|
||||
</Ref>
|
||||
</Set>
|
||||
<Set name="scavengeInterval">60</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance directly:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<!-- Expose the jetty infinispan classes for session serialization -->
|
||||
<Get name="serverClasspathPattern">
|
||||
<Call name="add">
|
||||
<Arg>-org.eclipse.jetty.session.infinispan.</Arg>
|
||||
</Call>
|
||||
</Get>
|
||||
|
||||
<!-- Reference the server directly -->
|
||||
<Get name="server">
|
||||
<Get id="idMgr" name="sessionIdManager"/>
|
||||
</Get>
|
||||
|
||||
<!-- Get a reference to the Cache via the InfinispanSessionIdManager -->
|
||||
<Ref id="idMgr">
|
||||
<Get id="cache" name="cache"/>
|
||||
</Ref>
|
||||
|
||||
<!-- Apply the SessionIdManager and Cache to the InfinispanSessionManager -->
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="mgr" class="org.eclipse.jetty.session.infinispan.InfinispanSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
<Set name="cache">
|
||||
<Ref id="cache">
|
||||
</Ref>
|
||||
</Set>
|
||||
<Set name="scavengeInterval">600</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
The InfinispanSessionManager can be provided by calling setters:
|
||||
|
||||
scavengeInterval::
|
||||
Time in seconds between runs of a scavenger task that looks for expired old sessions to delete.
|
||||
The default is 10 minutes.
|
||||
staleIntervalSec::
|
||||
The length of time a session can be in memory without being checked against the cluster.
|
||||
A value of 0 indicates that the session is never checked against the cluster - the current node is considered to be the master for the session.
|
||||
|
||||
===== Using HotRod
|
||||
|
||||
If you're using the hotrod client - where serialization will be required - you will need to ensure that the hotrod marshalling software works with Jetty classloading.
|
||||
To do this, firstly ensure that you have included the lines containing the `getServerClasspathPattern().add(...)` to your context xml file as shown above.
|
||||
|
||||
Then, create the file `${jetty.base}/resources/hotrod-client.properties`.
|
||||
Add the following line to this file:
|
||||
|
||||
....
|
||||
infinispan.client.hotrod.marshaller=org.eclipse.jetty.session.infinispan.WebAppMarshaller
|
||||
....
|
|
@ -1,228 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-clustering-jdbc]]
|
||||
=== Session Clustering with a Database
|
||||
|
||||
Jetty can support session clustering by persisting sessions to a shared database.
|
||||
Each Jetty instance locally caches sessions for which it has received requests, writing any changes to the session through to the database as the request exits the server.
|
||||
Sessions must obey the Serialization contract, and servlets must call the `Session.setAttribute()` method to ensure that changes are persisted.
|
||||
|
||||
The persistent session mechanism works in conjunction with a load balancer that supports stickiness.
|
||||
Stickiness can be based on various data items, such as source IP address or characteristics of the session ID or a load-balancer specific mechanism.
|
||||
For those load balancers that examine the session ID, the Jetty persistent session mechanism appends a node ID to the session ID, which can be used for routing.
|
||||
|
||||
In this type of solution, the database can become both a bottleneck and a single point of failure.
|
||||
Jetty takes steps to reduce the load on the database (discussed below), but in a heavily loaded environment you might need to investigate other optimization strategies such as local caching and database replication.
|
||||
You should also consult your database vendor's documentation for information on how to ensure high availability and failover of your database.
|
||||
|
||||
==== Configuration
|
||||
|
||||
There are two components to session management in Jetty: a session ID manager and a session manager.
|
||||
|
||||
* The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there can only be one session ID manager per Jetty instance.
|
||||
* The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.
|
||||
|
||||
These managers also cooperate and collaborate with the `org.eclipse.jetty.server.session.SessionHandler` to enable cross-context dispatch.
|
||||
|
||||
==== The jdbc-session Module
|
||||
|
||||
When using the jetty distribution, to enable jdbc session persistence, you will first need to enable the jdbc-session link:#startup-modules[module] for your link:#creating-jetty-base[base] using the `--add-to-start` argument to the link:#startup-overview[start.jar].
|
||||
|
||||
You will also find the following properties, either in your base's start.d/jdbc-session.ini file or appended to your start.ini, depending on how you enabled the module:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
## Unique identifier for this node in the cluster
|
||||
jetty.jdbcSession.workerName=node1
|
||||
|
||||
##Uncomment either the datasource name or driverClass and connectionURL
|
||||
#jetty.jdbcSession.datasource=sessions
|
||||
jetty.jdbcSession.driverClass=org.apache.derby.jdbc.EmbeddedDriver
|
||||
jetty.jdbcSession.connectionURL=jdbc:derby:sessions;create=true
|
||||
----
|
||||
|
||||
jetty.jdbcSession.workerName::
|
||||
The name that uniquely identifies this node in the cluster.
|
||||
This value will also be used by the sticky load balancer to identify the node.
|
||||
Don't forget to change the value of this property on *each* node on which you enable jdbc session clustering.
|
||||
jetty.jdbcSession.scavenge::
|
||||
The time in seconds between sweeps of a task which scavenges old expired sessions.
|
||||
The default is 10 minutess.
|
||||
Increasing the frequency is not recommended as doing so increases the load on the database with very little gain.
|
||||
jetty.jdbcSession.datasource::
|
||||
The name of a `javax.sql.DataSource` that gives access to the database that holds the session information.
|
||||
You should configure *either* this or the jdbc driver information described next.
|
||||
jetty.jdbcSession.datasource and jetty.jdbcSession.connectionURL::
|
||||
This is the name of the jdbc driver class, and a jdbc connection url suitable for that driver.
|
||||
You should configure *either* this or the jdbc datasource name described above.
|
||||
|
||||
These properties are applied to the `JDBCSessionIdManager` described below.
|
||||
|
||||
===== Configuring the JDBCSessionIdManager
|
||||
|
||||
The jdbc-session module will have installed file called `$\{jetty.home}/etc/jetty-jdbc-sessions.xml`.
|
||||
This file configures an instance of the `JDBCSessionIdManager` that will be shared across all webapps deployed on that server.
|
||||
It looks like this:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
include::{SRCDIR}/jetty-server/src/main/config/etc/jetty-jdbc-sessions.xml[]
|
||||
----
|
||||
|
||||
As well as uncommenting and setting up appropriate values for the properties discussed above, you will also need to edit this file and uncomment *either* the data source or the driver info elements.
|
||||
|
||||
As Jetty configuration files are direct mappings of XML to Java, it is straight forward to do this in code:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
Server server = new Server();
|
||||
...
|
||||
JDBCSessionIdManager idMgr = new JDBCSessionIdManager(server);
|
||||
idMgr.setWorkerName("node1");
|
||||
idMgr.setDriverInfo("com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/sessions?user=janb");
|
||||
idMgr.setScavengeInterval(600);
|
||||
server.setSessionIdManager(idMgr);
|
||||
|
||||
----
|
||||
|
||||
====== Configuring the Database Schema
|
||||
|
||||
You may find it necessary to change the names of the tables and columns that the JDBC Session management uses to store the session information.
|
||||
The defaults used are:
|
||||
|
||||
.Default Values for Session Id Table
|
||||
[options="header"]
|
||||
|===========================
|
||||
|table name |JettySessionIds
|
||||
|columns |id
|
||||
|===========================
|
||||
|
||||
.Default Values for Session Table
|
||||
[options="header"]
|
||||
|=======================================================================
|
||||
|table name |JettySessions
|
||||
|
||||
|columns |rowId, sessionId, contextPath, virtualHost, lastNode,
|
||||
accessTime, lastAccessTime, createTime, cookieTime, lastSavedTime,
|
||||
expiryTime, maxInterval, map
|
||||
|=======================================================================
|
||||
|
||||
To change these values, use the link:{JDURL}/org/eclipse/jetty/server/session/SessionIdTableSchema.html[org.eclipse.jetty.server.session.SessionIdTableSchema] and link:{JDURL}/org/eclipse/jetty/server/session/SessionTableSchema.html[org.eclipse.jetty.server.session.SessionTableSchema] classes.
|
||||
These classes have getter/setter methods for the table name and all columns.
|
||||
|
||||
Here's an example of changing the name of `JettySessionsId` table and its single column.
|
||||
This example will use java code, but as explained above, you may also do this via a Jetty xml configuration file:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
JDBCSessionIdManager idManager = new JDBCSessionIdManager(server);
|
||||
|
||||
SessionIdTableSchema idTableSchema = new SessionIdTableSchema();
|
||||
idTableSchema.setTableName("mysessionids");
|
||||
idTableSchema.setIdColumn("theid");
|
||||
idManager.setSessionIdTableSchema(idTableSchema);
|
||||
----
|
||||
|
||||
In a similar fashion, you can change the names of the table and columns for the `JettySessions` table.
|
||||
*Note* that both the `SessionIdTableSchema` and the `SessionTableSchema` instances are set on the `JDBCSessionIdManager` class.
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
JDBCSessionIdManager idManager = new JDBCSessionIdManager(server);
|
||||
|
||||
SessionTableSchema sessionTableSchema = new SessionTableSchema();
|
||||
sessionTableSchema.setTableName("mysessions");
|
||||
sessionTableSchema.setIdColumn("mysessionid");
|
||||
sessionTableSchema.setAccessTimeColumn("atime");
|
||||
sessionTableSchema.setContextPathColumn("cpath");
|
||||
sessionTableSchema.setCookieTimeColumn("cooktime");
|
||||
sessionTableSchema.setCreateTimeColumn("ctime");
|
||||
sessionTableSchema.setExpiryTimeColumn("extime");
|
||||
sessionTableSchema.setLastAccessTimeColumn("latime");
|
||||
sessionTableSchema.setLastNodeColumn("lnode");
|
||||
sessionTableSchema.setLastSavedTimeColumn("lstime");
|
||||
sessionTableSchema.setMapColumn("mo");
|
||||
sessionTableSchema.setMaxIntervalColumn("mi");
|
||||
idManager.setSessionTableSchema(sessionTableSchema);
|
||||
----
|
||||
|
||||
===== Configuring the JDBCSessionManager
|
||||
|
||||
As mentioned elsewhere, there should be one `JDBCSessionManager` per context (e.g. webapp).
|
||||
It will need to reference the single `JDBCSessionIdManager` configured previously for the Server.
|
||||
|
||||
The way you configure a `JDBCSessionManager` depends on whether you're configuring from a context xml file, a `jetty-web.xml` file or code.
|
||||
The basic difference is how you get a reference to the Jetty `org.eclipse.jetty.server.Server` instance.
|
||||
|
||||
From a context xml file, you reference the Server instance as a Ref:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Ref id="Server">
|
||||
<Call id="idMgr" name="getSessionIdManager"/>
|
||||
</Ref>
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New id="jdbcmgr" class="org.eclipse.jetty.server.session.JDBCSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance directly:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<Get name="server">
|
||||
<Get id="idMgr" name="sessionIdManager"/>
|
||||
</Get>
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.JDBCSessionManager">
|
||||
<Set name="sessionIdManager">
|
||||
<Ref id="idMgr"/>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
If you're embedding this in code:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
//assuming you have already set up the JDBCSessionIdManager as shown earlier
|
||||
//and have a reference to the Server instance:
|
||||
|
||||
WebAppContext wac = new WebAppContext();
|
||||
... //configure your webapp context
|
||||
JDBCSessionManager jdbcMgr = new JDBCSessionManager();
|
||||
jdbcMgr.setSessionIdManager(server.getSessionIdManager());
|
||||
SessionHandler sessionHandler = new SessionHandler(jdbcMgr);
|
||||
wac.setSessionHandler(sessionHandler);
|
||||
----
|
|
@ -1,240 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-clustering-mongodb]]
|
||||
=== Session Clustering with MongoDB
|
||||
|
||||
Jetty can support session clustering by persisting sessions into http://www.mogodb.org[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.
|
||||
|
||||
==== Configuration
|
||||
|
||||
There are two components to session management in Jetty: a session ID manager and a session manager.
|
||||
|
||||
* The session ID manager ensures that session IDs are unique across all webapps hosted on a Jetty instance, and thus there can only be one session ID manager per Jetty instance.
|
||||
* The session manager handles the session lifecycle (create/update/invalidate/expire) on behalf of a web application, so there is one session manager per web application instance.
|
||||
|
||||
These managers also cooperate and collaborate with the `org.eclipse.jetty.server.session.SessionHandler` to enable cross-context dispatch.
|
||||
|
||||
==== The nosql Module
|
||||
|
||||
When using the jetty distribution, to enable the MongoDB session persistence mechanism, you will first need to enable the nosql link:#startup-modules[module] for your link:#creating-jetty-base[base] using the `--add-to-start` argument to the link:#startup-overview[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:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
## 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`.
|
||||
|
||||
===== Configuring the MongoSessionIdManager
|
||||
|
||||
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:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
include::{SRCDIR}/jetty-nosql/src/main/config/etc/jetty-nosql.xml[]
|
||||
----
|
||||
|
||||
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:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<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:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
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.
|
||||
|
||||
scavengeDelay::
|
||||
How long to delay before periodically looking for sessions to scavenge?
|
||||
scavengePeriod::
|
||||
How much time after a scavenge has completed should you wait before doing it again?
|
||||
scavengeBlockSize::
|
||||
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.
|
||||
purge (Boolean)::
|
||||
Do you want to purge (delete) sessions that are invalid from the session store completely?
|
||||
purgeDelay::
|
||||
How often do you want to perform this purge operation?
|
||||
purgeInvalidAge::
|
||||
How old should an invalid session be before it is eligible to be purged?
|
||||
purgeValidAge::
|
||||
How old should a valid session be before it is eligible to be marked invalid and purged?
|
||||
Should this occur at all?
|
||||
purgeLimit::
|
||||
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.
|
||||
preserveOnStop::
|
||||
Whether or not to retain all sessions when the session manager stops.
|
||||
Default is `true`.
|
||||
|
||||
===== Configuring a MongoSessionManager
|
||||
|
||||
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 link:{JDURL}/org/eclipse/jetty/nosql/MongoSessionManager.html[org.eclipse.jetty.nosql.mongodb.MongoSessionManager] depends on whether you're configuring from a link:#deployable-descriptor-file[context xml] file or a link:#jetty-web-xml-config[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:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<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:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<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:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
//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));
|
||||
----
|
|
@ -1,281 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[setting-session-characteristics]]
|
||||
=== Setting Session Characteristics
|
||||
|
||||
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.
|
||||
Choosing the correct session manager implementation is an important consideration for every application as each can fit and perform optimally in different situations.
|
||||
If you need a simple in-memory session manager that can persist to disk then the `HashSessionManager` can be a good place to start.
|
||||
If you need a session manager that can work in a clustered scenario with multiple instances of Jetty, then the JDBC session manager can be an excellent option.
|
||||
Jetty also offers more niche session managers that leverage backends such as MongoDB, Inifinispan, or even Google's Cloud Data Store.
|
||||
|
||||
To modify the session characteristics of a web application, you can use the following parameters, applying them as in one of the example configurations:
|
||||
|
||||
[[using-init-parameters]]
|
||||
==== Using Init Parameters
|
||||
|
||||
Use these parameters to set session characteristics.
|
||||
|
||||
.Init Parameters
|
||||
[cols=",,",options="header",]
|
||||
|=======================================================================
|
||||
|Context Parameter |Default Value |Description
|
||||
|org.eclipse.jetty.servlet.SessionCookie |JSESSIONID |Session cookie
|
||||
name defaults to JSESSIONID, but can be set for a particular webapp with
|
||||
this context param.
|
||||
|
||||
|org.eclipse.jetty.servlet.SessionIdPathParameterName |jsessionid
|
||||
|Session URL parameter name. Defaults to jsessionid, but can be set for
|
||||
a particular webapp with this context param. Set to "none" to disable
|
||||
URL rewriting.
|
||||
|
||||
|org.eclipse.jetty.servlet.SessionDomain |- |Session Domain. If this
|
||||
property is set as a ServletContext param, then it is used as the domain
|
||||
for session cookies.If it is not set, then no domain is specified for
|
||||
the session cookie.
|
||||
|
||||
|org.eclipse.jetty.servlet.SessionPath |- |Session Path. If this
|
||||
property is set as a ServletContext param, then it is used as the path
|
||||
for the session cookie. If it is not set, then the context path is used
|
||||
as the path for the cookie.
|
||||
|
||||
|org.eclipse.jetty.servlet.MaxAge |-1 |Session Max Age. If this property
|
||||
is set as a ServletContext param, then it is used as the max age for the
|
||||
session cookie. If it is not set, then a max age of -1 is used.
|
||||
|
||||
|org.eclipse.jetty.servlet.CheckingRemoteSessionIdEncoding |false |If
|
||||
true, Jetty will add JSESSIONID parameter even when encoding external
|
||||
urls with calls to encodeURL(). False by default.
|
||||
|=======================================================================
|
||||
|
||||
[[applying-init-parameters]]
|
||||
===== Applying Init Parameters
|
||||
|
||||
The following sections provide examples of how to apply the init parameters.
|
||||
|
||||
[[context-parameter-example]]
|
||||
====== Context Parameter Example
|
||||
|
||||
You can set these parameters as context parameters in a web application's `WEB-INF/web.xml` file:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
...
|
||||
<context-param>
|
||||
<param-name>org.eclipse.jetty.servlet.SessionCookie</param-name>
|
||||
<param-value>XSESSIONID</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>org.eclipse.jetty.servlet.SessionIdPathParameterName</param-name>
|
||||
<param-value>xsessionid</param-value>
|
||||
</context-param>
|
||||
...
|
||||
</web-app>
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[web-application-examples]]
|
||||
====== Web Application Examples
|
||||
|
||||
You can configure init parameters on a web application, either in code, or in a Jetty context xml file equivalent:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/test</Set>
|
||||
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test</Set>
|
||||
|
||||
...
|
||||
|
||||
<Call name="setInitParameter">
|
||||
<Arg>org.eclipse.jetty.servlet.SessionCookie</Arg>
|
||||
<Arg>XSESSIONID</Arg>
|
||||
</Call>
|
||||
<Call name="setInitParameter">
|
||||
<Arg>org.eclipse.jetty.servlet.SessionIdPathParameterName</Arg>
|
||||
<Arg>xsessionid</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[init-parameter-examples]]
|
||||
====== SessionManager Examples
|
||||
|
||||
You can configure init parameters directly on a `SessionManager` instance, either in code or the equivalent in xml:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/test</Set>
|
||||
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test</Set>
|
||||
|
||||
...
|
||||
|
||||
<Get name="sessionHandler">
|
||||
<Set name="sessionManager">
|
||||
<New class="org.eclipse.jetty.server.session.HashSessionManager">
|
||||
<Set name="sessionCookie">XSESSIONID</Set>
|
||||
<Set name="sessionIdPathParameterName">xsessionid</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</Get>
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
==== Using Servlet 3.0 Session Configuration
|
||||
|
||||
With the advent of http://jcp.org/en/jsr/detail?id=315[Servlet Specification 3.0] there are new APIs for configuring session handling characteristics.
|
||||
What was achievable before only via Jetty-specific link:#session-init-params[init-parameters] can now be achieved in a container-agnostic manner either in code, or via `web.xml`.
|
||||
|
||||
[[session-cookie-configuration]]
|
||||
===== SessionCookieConfiguration
|
||||
|
||||
The http://docs.oracle.com/javaee/6/api/javax/servlet/SessionCookieConfig.html[javax.servlet.SessionCookieConfig] class can be used to set up session handling characteristics.
|
||||
For full details, consult the http://docs.oracle.com/javaee/6/api/javax/servlet/SessionCookieConfig.html[javadoc].
|
||||
|
||||
Below is an example of this implementation: a `ServletContextListener` retrieves the `SessionCookieConfig` and sets up some new values when the context is being initialized:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
public class TestListener implements ServletContextListener
|
||||
{
|
||||
|
||||
public void contextInitialized(ServletContextEvent sce)
|
||||
{
|
||||
String comment = "This is my special cookie configuration";
|
||||
String domain = "foo.com";
|
||||
String path = "/my/special/path";
|
||||
boolean isSecure = true;
|
||||
boolean httpOnly = false;
|
||||
int maxAge = 30000;
|
||||
String cookieName = "FOO_SESSION";
|
||||
|
||||
|
||||
SessionCookieConfig scf = sce.getServletContext().getSessionCookieConfig();
|
||||
|
||||
scf.setComment(comment);
|
||||
scf.setDomain(domain);
|
||||
scf.setHttpOnly(httpOnly);
|
||||
scf.setMaxAge(maxAge);
|
||||
scf.setPath(path);
|
||||
scf.setSecure(isSecure);
|
||||
scf.setName(cookieName);
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
You can also use `web.xml` to configure the session handling characteristics instead: here's an example doing exactly the same as above instead of using code:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="true"
|
||||
version="3.0">
|
||||
|
||||
<session-config>
|
||||
<cookie-config>
|
||||
<comment>This is my special cookie configuration</comment>
|
||||
<domain>foo.com</domain>
|
||||
<http-only>false</http-only>
|
||||
<max-age>30000</max-age>
|
||||
<path>/my/special/path</path>
|
||||
<secure>true</secure>
|
||||
<name>FOO_SESSION</name>
|
||||
</cookie-config>
|
||||
</session-config>
|
||||
</web-app>
|
||||
----
|
||||
|
||||
[[session-tracking-modes]]
|
||||
===== SessionTrackingModes
|
||||
|
||||
In addition to the configuration of link:#session-cookie-configuration[session cookies], since Servlet 3.0 you can also use the http://docs.oracle.com/javaee/6/api/javax/servlet/SessionTrackingMode.html[javax.servlet.SessionTrackingMode] to configure session tracking.
|
||||
|
||||
To determine what are the _default_ session tracking characteristics used by the container, call:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
javax.servlet.SessionContext.getDefaultSessionTrackingModes();
|
||||
----
|
||||
|
||||
This returns a java.util.Set of javax.servlet.SessionTrackingMode. The
|
||||
_default_ session tracking modes for Jetty are:
|
||||
|
||||
* http://docs.oracle.com/javaee/6/api/javax/servlet/SessionTrackingMode.html#COOKIE[SessionTrackingMode.COOKIE]
|
||||
* http://docs.oracle.com/javaee/6/api/javax/servlet/SessionTrackingMode.html#URL[SessionTrackingMode.URL]
|
||||
|
||||
To see which session tracking modes are actually in effect for this Context, the following call returns a `java.util.Set` of `javax.servlet.SessionTrackingMode`:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
javax.servlet.SessionContext.getEffectiveSessionTrackingModes();
|
||||
----
|
||||
|
||||
To change the session tracking modes, call:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
----
|
||||
javax.servlet.SessionContext.setSessionTrackingModes(Set<SessionTrackingMode>);
|
||||
----
|
||||
|
||||
You may also set the tracking mode in `web.xml`, e.g.:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
metadata-complete="true"
|
||||
version="3.0">
|
||||
|
||||
<session-config>
|
||||
<tracking-mode>URL</tracking-mode>
|
||||
<tracking-mode>COOKIE</tracking-mode>
|
||||
</session-config>
|
||||
</web-app>
|
||||
----
|
|
@ -1,117 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[using-persistent-sessions]]
|
||||
=== Using Persistent Sessions
|
||||
|
||||
It is sometimes useful to preserve existing Sessions across restarts of Jetty.
|
||||
The link:{JDURL}/org/eclipse/jetty/server/session/HashSessionManager.html[`HashSessionManager`] supports this feature.
|
||||
If you enable persistence, the `HashSessionManager` saves all existing, valid Sessions to disk before shutdown completes.
|
||||
On restart, Jetty restores the saved Sessions.
|
||||
|
||||
[[enabling-persistence]]
|
||||
==== Enabling Persistence
|
||||
|
||||
A `SessionManager` does just what its name suggests – it manages the lifecycle and state of sessions on behalf of a webapp.
|
||||
Each webapp must have its own unique `SessionManager` instance.
|
||||
Enabling persistence is as simple as configuring the `HashSessionManager` as the `SessionManager` for a webapp and telling it where on disk to store the sessions:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
.
|
||||
.
|
||||
.
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.HashSessionManager">
|
||||
<Set name="storeDirectory">your/chosen/directory/goes/here</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
.
|
||||
.
|
||||
.
|
||||
</Configure>
|
||||
|
||||
|
||||
----
|
||||
|
||||
The above uses an example of a xref:intro-jetty-configuration-contexts[context configuration file].
|
||||
|
||||
[TIP]
|
||||
====
|
||||
If you want to persist the sessions from multiple webapps:
|
||||
|
||||
1. Configure a separate `HashSessionManager` for each.
|
||||
|
||||
2. Assign to each a different value for `storeDirectory`.
|
||||
====
|
||||
|
||||
[[delaying-session-load]]
|
||||
==== Delaying Session Load
|
||||
|
||||
You might need to ensure that the sessions are loaded AFTER the servlet environment starts up (by default, Jetty eagerly loads sessions as part of the container startup, but before it initializes the servlet environment).
|
||||
For example, the Wicket web framework requires the servlet environment to be available when sessions are activated.
|
||||
|
||||
Using `SessionManager.setLazyLoad(true)`, Jetty loads sessions lazily either when it receives the first request for a session, or the session scavenger runs for the first time, whichever happens first.
|
||||
Here's how the configuration looks in XML:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<Set name="sessionHandler">
|
||||
<New class="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.HashSessionManager">
|
||||
<Set name="lazyLoad">true</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
----
|
||||
|
||||
[[enabling-persistence-for-jetty-maven-plugin]]
|
||||
==== Enabling Persistence for the Jetty Maven Plugin
|
||||
|
||||
To enable session persistence for the Jetty Maven plugin, set up the `HashSessionManager` in the configuration section like so:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>9.0.0.RC2 (or current version)</version>
|
||||
<configuration>
|
||||
<!-- ... -->
|
||||
<webAppConfig implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
|
||||
<defaultsDescriptor>${project.build.outputDirectory}/META-INF/webdefault.xml</defaultsDescriptor>
|
||||
<contextPath>${jetty.contextRoot}</contextPath>
|
||||
<sessionHandler implementation="org.eclipse.jetty.server.session.SessionHandler">
|
||||
<sessionManager implementation="org.eclipse.jetty.server.session.HashSessionManager">
|
||||
<storeDirectory>${project.basedir}/target/jetty-sessions</storeDirectory>
|
||||
<idleSavePeriod>1</idleSavePeriod>
|
||||
</sessionManager>
|
||||
</sessionHandler>
|
||||
</webAppConfig>
|
||||
<!-- ... -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
----
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-configuration-housekeeper]]
|
||||
=== The Base Sessions Module
|
||||
The `sessions` module is the base module that all other session modules depends upon.
|
||||
As such it will be _transitively_ enabled if you enable any of the other session modules: you need to _explicitly_ enable it if you wish to _change_ any settings from their defaults.
|
||||
|
||||
Enabling the `sessions` module puts the `$jetty.home/etc/sessions/id-manager.xml` file onto the execution path and generates a `$jetty.base/start.d/sessions.ini` file.
|
||||
|
||||
The `id-manager.xml` file instantiates a `DefaultSessionIdManager` and `HouseKeeper`.
|
||||
The former is used to generate and manage session ids whilst the latter is responsible for periodic scavenging of expired sessions.
|
||||
|
||||
The `sessions.ini` file can be used to configure them.
|
||||
|
||||
[[session-idmanager-housekeeper-config]]
|
||||
==== Configuration
|
||||
|
||||
jetty.sessionIdManager.workerName::
|
||||
This uniquely identifies the jetty server instance within a cluster.
|
||||
If you have more than one Jetty instance, it is *crucial* that you configure the worker name differently on each jetty instance.
|
||||
You can either provide a value for this property, or you can allow jetty to try and synthesize a workerName - the latter option is _only_ advisable in the case of a single, non-clustered deployment.
|
||||
There are two ways jetty will try to synthesize a default `workerName`:
|
||||
|
||||
* if running on GoogleAppEngine, the `workerName` will be formed by concatenating the values of the environment variables `JETTY_WORKER_INSTANCE` and `GAE_MODULE_INSTANCE`
|
||||
* otherwise, the `workerName` will be formed by concatenating the environment variable `JETTY_WORKER_INSTANCE` and the literal `0`.
|
||||
|
||||
|
||||
jetty.sessionScavengeInterval.seconds::
|
||||
This is the period in _seconds_ between runs of the `HouseKeeper`, responsible for orchestrating the removal of expired sessions.
|
||||
By default it will run every 600 secs (ie 10 mins).
|
||||
As a rule of thumb, you should ensure that the scavenge interval is shorter than the `<session-timeout>` of your sessions to ensure that they are promptly scavenged.
|
||||
|
||||
TIP: Don't forget that the `<session-timeout>` is specified in web.xml in _minutes_ and the vaue of the `jetty.sessionScavengeInterval.seconds` is in _seconds_.
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[configuring-sessions-file-system]]
|
||||
|
||||
=== Persistent Sessions: File System
|
||||
|
||||
Note: Persisting sessions to the local file system should *not* be used in a clustered environment.
|
||||
|
||||
==== Enabling File System Sessions
|
||||
|
||||
When using the Jetty distribution, you will first need to enable the `session-store-file` link:#startup-modules[module] for your link:#startup-base-and-home[Jetty base] using the `--add-to-start` argument on the command line.
|
||||
|
||||
[source,screen,subs="{sub-order}"]
|
||||
----
|
||||
[my-base]$ java -jar /path/to/jetty-home/start.jar --create-startd
|
||||
INFO : Base directory was modified
|
||||
|
||||
[my-base]$ java -jar /path/to/jetty-home/start.jar --add-to-start=session-store-file
|
||||
INFO : server transitively enabled, ini template available with --add-to-start=server
|
||||
INFO : sessions transitively enabled, ini template available with --add-to-start=sessions
|
||||
INFO : session-store-file initialized in ${jetty.base}/start.d/session-store-file.ini
|
||||
MKDIR : ${jetty.base}/sessions
|
||||
INFO : Base directory was modified
|
||||
----
|
||||
|
||||
Doing this enables the File System Session module and any dependent modules or files needed for it to run on the server.
|
||||
The example above is using a fresh `${jetty.base}` with nothing else enabled.
|
||||
|
||||
When the `--add-to-start` argument was added to the command line, it enabled the the `session-store-file` module as well as the `sessions` and `server` modules, which are required for the File System session management to operate.
|
||||
Additionally a `${jetty.base}/sessions` directory was created.
|
||||
By default Session files will be saved to this directory.
|
||||
|
||||
In addition to adding these modules to the classpath of the server, several ini configuration files were added to the `${jetty.base}/start.d` directory.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
Session data is now only loaded when requested.
|
||||
Previous functionality such as `setLazyLoad` has been removed.
|
||||
____
|
||||
|
||||
==== Configuring File System Session Properties
|
||||
|
||||
Opening `start.d/session-store-file.ini` will show a list of all the configurable options for the file system session module:
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
----
|
||||
# ---------------------------------------
|
||||
# Module: session-store-file
|
||||
# Enables session persistent storage in files.
|
||||
# ---------------------------------------
|
||||
--module=session-store-file
|
||||
|
||||
jetty.session.file.storeDir=${jetty.base}/sessions
|
||||
#jetty.session.file.deleteUnrestorableFiles=false
|
||||
#jetty.session.savePeriod.seconds=0
|
||||
----
|
||||
|
||||
jetty.session.storeDir::
|
||||
This defines the location for storage of Session files.
|
||||
jetty.session.file.deleteUnrestorableFiles::
|
||||
Boolean.
|
||||
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.
|
||||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
[NOTE]
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-configuration-housekeeper]]
|
||||
=== The SessionIdManager and the Housekeeper
|
||||
|
||||
==== Default Settings
|
||||
By default, Jetty will instantiate a single instance of the `DefaultSessionIdManager` and `HouseKeeper` at startup with default settings.
|
||||
|
||||
The default settings are:
|
||||
|
||||
DefaultSessionIdManager: worker name::
|
||||
This uniquely identifies the jetty server instance within a cluster.
|
||||
It is set from the value of the `JETTY_WORKER_INSTANCE` environment variable, or `node0` if the environment value is not set.
|
||||
If you have more than one Jetty instance, it is *crucial* that you explicitly configure the worker name on each Jetty instance (see link:#session-idmanager-housekeeper-config[below] for how to configure).
|
||||
|
||||
HouseKeeper: scavenge interval::
|
||||
This is the period in seconds between runs of the session scavenger, and by default is set to the equivalent of 10 minutes.
|
||||
As a rule of thumb, you should ensure that the scavenge interval is shorter than the `maxInactiveInterval` of your sessions to ensure that they are promptly scavenged.
|
||||
See below for instructions on how to configure this.
|
||||
|
||||
[[session-idmanager-housekeeper-config]]
|
||||
==== Configuration
|
||||
To change the default values, use the link:#startup-modules[module system] to link:#startup-modules[enable] the `sessions` module.
|
||||
|
||||
This will enable the `$jetty.home/etc/sessions/id-manager.xml` file and generate a `$jetty.base/start.d/sessions.ini` file.
|
||||
|
||||
The `id-manager.xml` file instantiates a single `DefaultSessionIdManager` and `HouseKeeper` and configures them using the properties from the `sessions.ini` file.
|
||||
|
||||
Edit the ini file to change the properties to easily customize the `DefaultSessionIdManager` and `HouseKeeper`:
|
||||
|
||||
jetty.sessionIdManager.workerName::
|
||||
By default it is `node1`.
|
||||
This uniquely identifies the Jetty server instance within a cluster.
|
||||
If you have more than one Jetty instance, it is crucial that you configure the worker name differently on each jetty instance.
|
||||
|
||||
|
||||
jetty.sessionScavengeInterval.seconds::
|
||||
This is the period in seconds between runs of the session scavenger.
|
||||
By default it will run every 600 secs (ie 10 mins).
|
||||
As a rule of thumb, you should ensure that the scavenge interval is shorter than the maxInactiveInterval of your sessions to ensure that they are promptly scavenged.
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[configuring-sessions-memory]]
|
||||
|
||||
=== Non-Persistent Sessions
|
||||
|
||||
Non-clustered, non-persistent, in-memory-only is the default style of session management.
|
||||
In previous versions of Jetty this was referred to as "hash" sessions, as they were stored in a `HashMap` in memory.
|
||||
|
||||
This is delivered by a combination of the `DefaultSessionCache` (to keep sessions in memory) and a `NullSessionDataStore` (to avoid session persistence).
|
||||
|
||||
If you do nothing, Jetty will instantiate one of each of these objects for each context at startup time using hard-coded defaults.
|
||||
|
||||
To explicitly set up non-persisted sessions using modules, use both the `session-cache-hash` and the `session-store-null` modules.
|
||||
|
||||
Enabling the modules allows you to configure behavior - see link:#session-configuration-sessioncache[the L1 Session Cache] for detailed information on configuration options for the `DefaultSessionCache`.
|
||||
The `NullSessionDataStore` has no customizable options.
|
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[configuring-sessions-file-system]]
|
||||
|
||||
=== Persistent Sessions: File System
|
||||
|
||||
The `session-store-file` module supports persistent storage of session data in a filesystem.
|
||||
|
||||
IMPORTANT: Persisting sessions to the local file system should *never* be used in a clustered environment.
|
||||
|
||||
==== Enabling File System Session Storage
|
||||
|
||||
When using the Jetty distribution, you will first need to enable the `session-store-file` xref:startup-modules[module] for your link:#startup-base-and-home[Jetty base] using the `--add-to-start` argument on the command line.
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
----
|
||||
$ java -jar ../start.jar --create-startd
|
||||
INFO : Base directory was modified
|
||||
|
||||
$ java -jar ../start.jar --add-to-start=session-store-file
|
||||
INFO : server transitively enabled, ini template available with --add-to-start=server
|
||||
INFO : sessions transitively enabled, ini template available with --add-to-start=sessions
|
||||
INFO : session-store-file initialized in ${jetty.base}/start.d/session-store-file.ini
|
||||
MKDIR : ${jetty.base}/sessions
|
||||
INFO : Base directory was modified
|
||||
----
|
||||
|
||||
Doing this enables this and any dependent modules or files needed for it to run on the server.
|
||||
The example above is using a fresh `${jetty.base}` with nothing else enabled.
|
||||
|
||||
Enabling this module also creates the `${jetty.base}/sessions` directory.
|
||||
By default session data will be saved to this directory, one file representing each session.
|
||||
|
||||
File names follow this pattern:
|
||||
|
||||
+[expiry]_[context]_[id]+
|
||||
|
||||
expiry::
|
||||
This is the expiry time in milliseconds since the epoch.
|
||||
context::
|
||||
This is a string representation of the context to which the session is scoped.
|
||||
It is comprised of the (sanitised) context path and the virtual host:
|
||||
+[contextpath]_[virtualhost]+
|
||||
contextpath:::
|
||||
This is the context path with any special characters, including `/`, replaced by the `_` underscore 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, then `0.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`
|
||||
|
||||
|
||||
==== Configuring
|
||||
|
||||
The `$jetty.base/start.d/sessions.ini` file contains the following properties which may be modified to customise filesystem session storage:
|
||||
|
||||
jetty.session.storeDir::
|
||||
Filesystem path.
|
||||
The default is `${jetty.base}/sessions`.
|
||||
This defines the location for storage of session files.
|
||||
|
||||
jetty.session.file.deleteUnrestorableFiles::
|
||||
Boolean.
|
||||
Default is `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.
|
||||
|
||||
jetty.session.savePeriod.seconds::
|
||||
Integer.
|
||||
Default is `0`.
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that jetty will skip persisting the session if only the access time changed, unless the time since the last save exceeds the value of this property.
|
|
@ -206,10 +206,7 @@ When the `--add-to-start` argument was added to the command line the first time,
|
|||
|
||||
In addition to adding these modules to the classpath of the server it also added the respective configuration files to the `${jetty.base}start.d` directory.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
____
|
||||
NOTE: If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
|
||||
==== Configuring GCloud Session Properties
|
||||
|
||||
|
@ -249,14 +246,14 @@ Amount of time, in seconds, to wait for other nodes to be checked to verify an e
|
|||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
||||
====
|
||||
|
||||
jetty.session.gcloud.maxRetries::
|
||||
Maxmium number of tries to connect to GCloud DataStore to write sessions.
|
|
@ -64,10 +64,7 @@ It also downloaded the needed Hazelcast-specific jar files and created a directo
|
|||
|
||||
In addition to adding these modules to the classpath of the server it also added several ini configuration files to the `${jetty.base}/start.d` directory.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
____
|
||||
NOTE: If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
|
||||
==== Configuring Hazelcast Remote Properties
|
||||
|
||||
|
@ -102,16 +99,16 @@ Amount of time, in seconds, to wait for other nodes to be checked to verify an e
|
|||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
|
||||
Be aware that if your session attributes contain classes from inside your webapp (or jetty classes) then you will need to put these classes onto the classpath of all of your hazelcast instances.
|
||||
____
|
||||
====
|
||||
|
||||
==== Configuring Embedded Hazelcast Clustering
|
||||
|
||||
|
@ -185,13 +182,13 @@ Amount of time, in seconds, to wait for other nodes to be checked to verify an e
|
|||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
|
||||
If your session attributes contain classes from inside your webapp (or jetty classes) then you will need to put these classes onto the classpath of all of your hazelcast instances. In the case of embedded hazelcast, as it is started before your webapp, it will NOT have access to your webapp's classes - you will need to extract these classes and put them onto the jetty server's classpath.
|
||||
____
|
||||
====
|
|
@ -1,46 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[jetty-sessions-architecture]]
|
||||
=== Session Architecture
|
||||
|
||||
==== Session Architecture Hierarchy
|
||||
|
||||
Each Jetty instance has a singular `SessionIdManager` to handle all session requests, regardless of clustering technology.
|
||||
For each context on the server there is one (1) `SessionCache` which contains all of the Session objects for the given context.
|
||||
The benefit of the `SessionCache` is to ensure that simultaneous requests accessing the same Session Id in the same context always operate on the same Session object.
|
||||
The SessionCache implementation supplied with the Jetty distribution does just that: keeps Session objects in memory so that they can be shared between simultaneous requests.
|
||||
However, it is possible to provide your own implementation that never shares Session objects should you require it.
|
||||
|
||||
Where the `SessionCache` handles Session information, Session data is stored in a `SessionDataStore` that is specific to the clustering technology being implemented.
|
||||
There is only one (1) `SessionDataStore` per `SessionCache`.
|
||||
|
||||
Visually the session architecture can be represented like this:
|
||||
|
||||
image::SessionsHierarchy.png[]
|
||||
|
||||
==== Configuring Sessions in the Jetty Distribution
|
||||
|
||||
Configuring session management involves selecting a link:#startup-modules[module] for the desired type of link:#session-configuration-sessioncache[session caching] behavior, and a module for the type of session persistence.
|
||||
|
||||
Jetty provides two different session caches: the `DefaultSessionCache` which holds sessions in memory, and the `NullSessionCache` which does not.
|
||||
There is more information on both of these types of session caching and the circumstances which would lead you to select one or the other in the link:#sessions-details[Session Components] section, and more information on the configuration options of each in link:#session-configuration-sessioncache[the L1 Session Cache] section.
|
||||
|
||||
For session persistence, Jetty provides a number of different implementations from which to choose including link:#configuring-sessions-memory[non-persistence], link:#configuring-sessions-file-system[local file storage], clustered technologies such as link:#configuring-sessions-jdbc[JDBC], link:#configuring-sessions-mongo[MongoDB], link:#configuring-sessions-infinispan[Inifinispan], link:#configuring-sessions-gcloud[Google Cloud Datastore], and link:#configuring-sessions-hazelcast[Hazelcast].
|
||||
|
||||
Depending on your persistence technology, to enhance performance, you may want to use an L2 cache for session data, in which case Jetty provides the link:#session-configuration-memcachedsessiondatastore[memcached L2 session data cache].
|
|
@ -63,10 +63,7 @@ It also downloaded the needed Infinispan-specific jar files and created a direct
|
|||
|
||||
In addition to adding these modules to the classpath of the server it also added several ini configuration files to the `${jetty.base}/start.d` directory.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
____
|
||||
NOTE: If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
|
||||
==== Configuring Inifinspan Remote Properties
|
||||
|
||||
|
@ -100,13 +97,13 @@ jetty.session.savePeriod.seconds=0::
|
|||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
||||
====
|
||||
|
||||
==== Configuring the Remote Infinispan Query Module
|
||||
|
||||
|
@ -126,10 +123,7 @@ There are no configuration properties associated with this module.
|
|||
During testing, it can be helpful to run an in-process instance of Infinispan.
|
||||
To enable this you will first need to enable the `session-store-infinispan-embedded` link:#startup-modules[module] for your link:#startup-base-and-home[Jetty base] using the `--add-to-start` argument on the command line.
|
||||
|
||||
____
|
||||
[IMPORTANT]
|
||||
If you are running Jetty with JDK 9 or greater, enable `session-store-infinispan-embedded-910.mod` instead.
|
||||
____
|
||||
IMPORTANT: If you are running Jetty with JDK 9 or greater, enable `session-store-infinispan-embedded-910.mod` instead.
|
||||
|
||||
[source,screen,subs="{sub-order}"]
|
||||
----
|
||||
|
@ -184,15 +178,14 @@ Amount of time, in seconds, to wait for other nodes to be checked to verify an e
|
|||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
||||
|
||||
====
|
||||
|
||||
==== Configuring Inifinspan Embedded Query
|
||||
|
||||
|
@ -213,10 +206,8 @@ Prior to release 9.4.13 we used the default Infinispan serialization, however th
|
|||
See issue https://github.com/eclipse/jetty.project/issues/2919 for more background.
|
||||
|
||||
We have provided a conversion program which will convert any sessions stored in Infinispan to the new format.
|
||||
____
|
||||
[IMPORTANT]
|
||||
We recommend that you backup your stored sessions before running the conversion program.
|
||||
____
|
||||
|
||||
IMPORTANT: We recommend that you backup your stored sessions before running the conversion program.
|
||||
|
||||
How to use the converter:
|
||||
|
|
@ -37,79 +37,29 @@ INFO : session-store-jdbc initialized in ${jetty.base}/start.d/session-store-jd
|
|||
INFO : Base directory was modified
|
||||
----
|
||||
|
||||
Doing this enables the JDBC Session module and any dependent modules or files needed for it to run on the server.
|
||||
Doing this enables the JDBC session module and any dependent modules or files needed for it to run on the server.
|
||||
The example above is using a fresh `${jetty.base}` with nothing else enabled.
|
||||
|
||||
When the `--add-to-start` argument was added to the command line, it enabled the the `session-store-jdbc` module as well as the `sessions` and `server` modules, which are required for JDBC session management to operate.
|
||||
==== Configuring
|
||||
|
||||
In addition to adding these modules to the classpath of the server, several ini configuration files were added to the `${jetty.base}/start.d` directory.
|
||||
|
||||
==== Configuring JDBC Session Properties
|
||||
|
||||
Opening the `start.d/session-store-jdbc.ini` will show a list of all the configurable options for the JDBC module:
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
----
|
||||
# ---------------------------------------
|
||||
# Module: session-store-jdbc
|
||||
# Enables JDBC persistent/distributed session storage.
|
||||
# ---------------------------------------
|
||||
--module=session-store-jdbc
|
||||
|
||||
##
|
||||
##JDBC Session properties
|
||||
##
|
||||
|
||||
#jetty.session.gracePeriod.seconds=3600
|
||||
|
||||
## Connection type:Datasource
|
||||
db-connection-type=datasource
|
||||
#jetty.session.jdbc.datasourceName=/jdbc/sessions
|
||||
|
||||
## Connection type:driver
|
||||
#db-connection-type=driver
|
||||
#jetty.session.jdbc.driverClass=
|
||||
#jetty.session.jdbc.driverUrl=
|
||||
|
||||
## Session table schema
|
||||
#jetty.session.jdbc.schema.accessTimeColumn=accessTime
|
||||
#jetty.session.jdbc.schema.contextPathColumn=contextPath
|
||||
#jetty.session.jdbc.schema.cookieTimeColumn=cookieTime
|
||||
#jetty.session.jdbc.schema.createTimeColumn=createTime
|
||||
#jetty.session.jdbc.schema.expiryTimeColumn=expiryTime
|
||||
#jetty.session.jdbc.schema.lastAccessTimeColumn=lastAccessTime
|
||||
#jetty.session.jdbc.schema.lastSavedTimeColumn=lastSavedTime
|
||||
#jetty.session.jdbc.schema.idColumn=sessionId
|
||||
#jetty.session.jdbc.schema.lastNodeColumn=lastNode
|
||||
#jetty.session.jdbc.schema.virtualHostColumn=virtualHost
|
||||
#jetty.session.jdbc.schema.maxIntervalColumn=maxInterval
|
||||
#jetty.session.jdbc.schema.mapColumn=map
|
||||
#jetty.session.jdbc.schema.table=JettySessions
|
||||
# Optional name of the schema used to identify where the session table is defined in the database:
|
||||
# "" - empty string, no schema name
|
||||
# "INFERRED" - special string meaning infer from the current db connection
|
||||
# name - a string defined by the user
|
||||
#jetty.session.jdbc.schema.schemaName
|
||||
# Optional name of the catalog used to identify where the session table is defined in the database:
|
||||
# "" - empty string, no catalog name
|
||||
# "INFERRED" - special string meaning infer from the current db connection
|
||||
# name - a string defined by the user
|
||||
#jetty.session.jdbc.schema.catalogName
|
||||
----
|
||||
The persistence of sessions via jdbc can be customized by editing the `${jetty.base}/start.d/session-store-jdbc.ini` file.
|
||||
The following properties are available:
|
||||
|
||||
jetty.session.gracePeriod.seconds::
|
||||
Integer.
|
||||
|
||||
Amount of time, in seconds, to wait for other nodes to be checked to verify an expired session is in fact expired throughout the cluster before closing it.
|
||||
jetty.session.savePeriod.seconds=0::
|
||||
jetty.session.savePeriod.seconds::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
||||
====
|
||||
|
||||
db-connection-type::
|
||||
Set to either `datasource` or `driver` depending on the type of connection being used.
|
|
@ -61,10 +61,7 @@ It also downloaded the needed Mongo-specific jar file and created a directory na
|
|||
|
||||
In addition to adding these modules to the classpath of the server, several ini configuration files were added to the `${jetty.base}/start.d` directory.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
____
|
||||
NOTE: If you have updated versions of the jar files automatically downloaded by Jetty, you can place them in the associated `${jetty.base}/lib/` directory and use the `--skip-file-validation=<module name>` command line option to prevent errors when starting your server.
|
||||
|
||||
==== Configuring MongoDB Session Properties
|
||||
|
||||
|
@ -96,14 +93,14 @@ Amount of time, in seconds, to wait for other nodes to be checked to verify an e
|
|||
jetty.session.savePeriod.seconds=0::
|
||||
By default whenever the last concurrent request leaves a session, that session is always persisted via the `SessionDataStore`, even if the only thing that changed on the session is its updated last access time.
|
||||
A non-zero value means that the `SessionDataStore` will skip persisting the session if only the access time changed, and it has been less than `savePeriod` seconds since the last time the session was written.
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Configuring `savePeriod` is useful if your persistence technology is very slow/costly for writes.
|
||||
In a clustered environment, there is a risk of the last access time of the session being out-of-date in the shared store for up to `savePeriod` seconds.
|
||||
This allows the possibility that a node may prematurely expire the session, even though it is in use by another node.
|
||||
Thorough consideration of the `maxIdleTime` of the session when setting the `savePeriod` is imperative - there is no point in setting a `savePeriod` that is larger than the `maxIdleTime`.
|
||||
____
|
||||
====
|
||||
|
||||
jetty.session.mongo.dbName::
|
||||
Name of the database in Mongo used to store the Session collection.
|
||||
|
@ -122,10 +119,10 @@ Used when utilizing MongoURI for secured connections.
|
|||
jetty.session.mongo.connectionString;;
|
||||
The string defining the MongoURI value, such as `mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]`.
|
||||
More information on how to format the MongoURI string can be found in the https://docs.mongodb.com/manual/reference/connection-string/[official documentation for mongo.]
|
||||
+
|
||||
____
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
You will only use *one* `connection-type` at a time, `address` or `uri`.
|
||||
If both are utilized in your `session-store-mongo.ini`, only the last `connection-type` configured in the file will be used.
|
||||
By default, the `connection-type` of `address` is used.
|
||||
____
|
||||
====
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[jetty-sessions-architecture]]
|
||||
|
||||
=== Session Overview
|
||||
|
||||
==== Terminology
|
||||
|
||||
Before diving into the specifics of how to plug-in and configure various alternative http session management modules, let's review some useful terminology:
|
||||
|
||||
SessionIdManager:: A jetty instance can have a single SessionIdManager that is responsible for managing session ids.
|
||||
HouseKeeper:: A jetty instance can have a single HouseKeeper that is responsible for finding and orchestrating the removal of expired sessions.
|
||||
SessionCache:: A context can have a single SessionCache that is an L1 cache of in-use session objects.
|
||||
SessionDataStore:: A context can have a single SessionDataStore that is responsible for all persistence operations on sessions.
|
||||
CachingSessionDataStore:: A context can have a single CachingSessionDataStore that is an L2 cache of session data.
|
||||
SessionHandler:: A context can have a single SessionHandler that is responsible for managing the lifecycle of sessions.
|
||||
|
||||
More details on these concepts can be found in the [Programming Guide].
|
||||
|
||||
==== Jetty Session Modules
|
||||
|
||||
There are a number of modules that offer pluggable alternatives for http session management.
|
||||
You can design how you want to cache and store http sessions by selecting alternative combinations of session modules.
|
||||
|
||||
For example, jetty ships with two alternative implementations of the `SessionCache`: one that caches sessions in memory (`session-cache-hash.mod`) and a trivial implementation that does not actually cache (`session-cache-null.mod`).
|
||||
|
||||
There are at least six alternative implementations of the `SessionDataStore` that you can use to persist your http sessions.
|
||||
The list current includes support for:
|
||||
|
||||
* file system storage (`session-store-file.mod`)
|
||||
* relational database storage (`session-store-jdbc.mod`)
|
||||
* NoSQL database storage (`session-store-mongo.mod`)
|
||||
* Google Cloud datastore storage (`session-store-gcloud.mod`)
|
||||
* Hazelcast storage (`session-store-hazelcast-remote.mod` or `session-store-hazelcast-embedded.mod`)
|
||||
* Infinispan storage (`session-store-infinispan-remote.mod` or `session-store-infinispan-embedded.mod`)
|
||||
|
||||
You might like to consult the [use-cases] to help you decide which combinations best suit your needs.
|
||||
|
||||
TIP: It is worth noting that if you do not configure _any_ session modules, jetty will still provide http sessions that are cached in memory but are never persisted.
|
|
@ -17,25 +17,23 @@
|
|||
//
|
||||
|
||||
[[session-configuration-sessioncache]]
|
||||
=== The L1 Session Cache
|
||||
=== SessionCache Alternatives
|
||||
|
||||
==== The DefaultSessionCache
|
||||
In this section we will look at the alternatives for the `SessionCache`, ie the L1 cache of in-use session objects.
|
||||
Jetty ships with two alternatives: an in-memory cache, and a null cache.
|
||||
The latter does not actually do any caching of sessions, and can be useful if you either want to minimize your support for sessions, or you are in a clustered deployment without a sticky loadbalancer.
|
||||
|
||||
In the absence of any explicit configuration, Jetty will instantiate an instance of the `DefaultSessionCache` per context.
|
||||
If you wish to change any of the default values, you need to enable the `session-cache-hash` link:#startup-modules[module].
|
||||
The [use-cases] go into more detail on these scenarios.
|
||||
|
||||
Once the `session-cache-hash` module has been enabled, you can view a list of all the configurable values by opening `start.d/session-cache-hash.ini`:
|
||||
==== Sessions Cached in Memory
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
----
|
||||
--module=session-cache-hash
|
||||
If you wish to change any of the default configuration values you should enable the `session-cache-hash` link:#startup-modules[module].
|
||||
The name `hash` harks back to historical jetty session implementations, whereby sessions were kept in memory using a HashMap.
|
||||
|
||||
#jetty.session.evictionPolicy=-1
|
||||
#jetty.session.saveOnInactiveEvict=false
|
||||
#jetty.session.saveOnCreate=false
|
||||
#jetty.session.removeUnloadableSessions=false
|
||||
#jetty.session.flushOnResponseCommit=false
|
||||
----
|
||||
After you have enabled the `session-cache-hash` module, the `$jetty.base/start.d/session-cache-hash.ini` will be generated.
|
||||
Edit this file to change the properties that control the behaviour of the cache.
|
||||
|
||||
===== Configuration
|
||||
|
||||
jetty.session.evictionPolicy::
|
||||
Integer.
|
||||
|
@ -47,14 +45,11 @@ Values are:
|
|||
* 0 : sessions are evicted from the cache as soon as the last active request for it finishes
|
||||
* >= 1 : any positive number is the time in seconds after which a session that is in the cache but has not experienced any activity will be evicted
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
If you are not using a `SessionDataStore` that persists sessions, be aware that evicted sessions will be lost.
|
||||
____
|
||||
NOTE: If you are not using one of the session persistence modules, ie one of the `session-store-xxxx.mod`s, then sessions will be lost when the context is stopped.
|
||||
|
||||
jetty.session.saveOnInactiveEvict::
|
||||
Boolean, default `false`.
|
||||
Controls whether a session will be saved to the `SessionDataStore` just prior to its eviction.
|
||||
Controls whether a session will be persisted to the `SessionDataStore` just prior to its eviction.
|
||||
|
||||
jetty.session.saveOnCreate::
|
||||
Boolean, default `false`.
|
||||
|
@ -62,7 +57,7 @@ Controls whether a session that is newly created will be immediately saved to th
|
|||
|
||||
jetty.session.removeUnloadableSessions::
|
||||
Boolean, default `false`.
|
||||
Controls whether a session that cannot be restored - for example because it is corrupted - from the `SessionDataStore` is deleted by the `SessionDataStore`.
|
||||
Controls whether the session cache should ask a `SessionDataStore` to delete a session that cannot be restored - for example because it is corrupted.
|
||||
|
||||
jetty.session.flushOnResponseCommit::
|
||||
Boolean, default `false`.
|
||||
|
@ -70,17 +65,17 @@ If true, if a session is "dirty" - ie its attributes have changed - it will be w
|
|||
This ensures that all subsequent requests whether to the same or different node will see the updated session data.
|
||||
If false, a dirty session will only be written to the backing store when the last simultaneous request for it leaves the session.
|
||||
|
||||
For more general information on the uses of these configuration properties, see link:#sessions-details[Session Components].
|
||||
jetty.session.invalidateOnShutdown::
|
||||
Boolean, default `false`.
|
||||
If true, when a context is shutdown, all sessions in the cache are invalidated and deleted both from the cache and from the `SessionDataStore`.
|
||||
|
||||
|
||||
==== The NullSessionCache
|
||||
==== Sessions Not Cached
|
||||
|
||||
The `NullSessionCache` is a trivial implementation of the `SessionCache` that does not cache any session information.
|
||||
You may need to use it if your clustering setup does not have a sticky load balancer, or if you want absolutely minimal support for sessions.
|
||||
If you use this in conjunction with the `NullSessionDataStore`, then sessions will neither be retained in memory nor persisted.
|
||||
You may need to use the `session-cache-null.mod` if your clustering setup does not have a sticky load balancer, or if you want absolutely minimal support for sessions.
|
||||
If you enable this module, but you don't enable a module that provides session persistence (ie one of the `session-store-xxx.mod` modules), then sessions will _neither_ be retained in memory _nor_ persisted.
|
||||
|
||||
To enable the `NullSessionCache`, enable the `sesssion-cache-null` link:#startup-modules[module].
|
||||
Configuration options are:
|
||||
===== Configuration
|
||||
|
||||
jetty.session.saveOnCreate::
|
||||
Boolean, default `false`.
|
||||
|
@ -88,12 +83,10 @@ Controls whether a session that is newly created will be immediately saved to th
|
|||
|
||||
jetty.session.removeUnloadableSessions::
|
||||
Boolean, default `false`.
|
||||
Controls whether a session that cannot be restored - for example because it is corrupted - from the `SessionDataStore` is deleted by the `SessionDataStore`.
|
||||
Controls whether the session cache should ask a `SessionDataStore` to delete a session that cannot be restored - for example because it is corrupted.
|
||||
|
||||
jetty.session.flushOnResponseCommit::
|
||||
Boolean, default `false`.
|
||||
If true, if a session is "dirty" - ie its attributes have changed - it will be written to the backing store as the response is about to commit.
|
||||
This ensures that all subsequent requests whether to the same or different node will see the updated session data.
|
||||
If false, a dirty session will only be written to the backing store when the last simultaneous request for it leaves the session.
|
||||
|
||||
For more general information on the uses of these configuration properties, see link:#sessions-details[Session Components].
|
|
@ -42,7 +42,7 @@ If you have a high likelihood of simultaneous requests for the same session obje
|
|||
|
||||
Without a sticky load balancer requests for the same session may arrive on any node in the cluster.
|
||||
This means it is likely that the copy of the Session object in any `SessionCache` is likely to be out-of-date, as the Session was probably last accessed on a different node.
|
||||
In this case, your `choices` are to use either the `NullSessionCache` or to de-tune the `DefaultSessionCache`.
|
||||
In this case, your choices are to use either the `NullSessionCache` or to de-tune the `DefaultSessionCache`.
|
||||
If you use the NullSessionCache all Session object caching is avoided.
|
||||
This means that every time a request references a session it must be brought in from persistent storage.
|
||||
It also means that there can be no sharing of Session objects for multiple requests for the same session: each will have their own Session object.
|
||||
|
@ -54,7 +54,7 @@ Again, due to the lack of Session transactionality, the ordering outcome of writ
|
|||
As the Session is cached while at least one request is accessing it, it is possible for multiple simultaneous requests to share the same Session object.
|
||||
|
||||
|
||||
==== Handling corrupted or unloadable session data
|
||||
==== Handling Corrupted or Unloadable Session Data
|
||||
|
||||
For various reasons it might not be possible for the `SessionDataStore` to re-read a stored session.
|
||||
One scenario is that the session stores a serialized object in it's attributes, and after a redeployment there in an incompatible class change.
|
||||
|
@ -88,8 +88,8 @@ Below is an example of how you could configure a the link:#configuring-sessions-
|
|||
|
||||
The example above functions in either a `jetty-web.xml` file or a link:#using-basic-descriptor-files[context xml descriptor file.]
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
====
|
||||
If you explicitly configure the `SessionCache` and `SessionDataStore` for a `SessionHandler` in a context xml file or `jetty-web.xml` file, any session modules you already have enabled are ignored.
|
||||
So, for example, if you had enabled the `session-store-gcloud module` for your sever, you could force a particular webapp to use the `FileSessionDataStore` by explicitly configuring it in either a context xml file or a `jetty-web.xml` file as shown above.
|
||||
____
|
||||
====
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[sessions-details]]
|
||||
=== Session Components
|
||||
|
||||
==== SessionIdManager
|
||||
|
||||
There is a maximum of one (1) `SessionIdManager` per Jetty Server instance.
|
||||
Its purpose is to generate fresh, unique session ids and to coordinate the re-use of session ids amongst co-operating contexts.
|
||||
|
||||
Unlike in previous versions of Jetty, 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.
|
||||
If you do not explicitly enable one of the session modules or otherwise configure a `SessionIdManager`, the `DefaultSessionIdManager` will be used.
|
||||
|
||||
If the `DefaultSessionIdManager` does not meet your needs, you can extend the `org.eclipse.jetty.server.session.AbstractSessionIdManager` or do a fresh implementation of the `org.eclipse.jetty.server.session.SessionIdManager` interface.
|
||||
|
||||
See link:#session-configuration-housekeeper[Configuring the SessionIdManager and HouseKeeper] for details on configuration.
|
||||
|
||||
==== HouseKeeper
|
||||
|
||||
There is a maximum of one (1) `HouseKeeper` per `SessionIdManager`.
|
||||
Its purpose is to periodically poll the `SessionHandlers` to clean out expired sessions.
|
||||
|
||||
By default the `HouseKeeper` will poll the `SessionHandlers` every 10 mins to find and delete expired sessions, although this interval is configurable.
|
||||
|
||||
See link:#session-configuration-housekeeper[Configuring the SessionIdManager and HouseKeeper] for details on configuration.
|
||||
|
||||
|
||||
==== SessionCache
|
||||
|
||||
There is one (1) `SessionCache` *per context.*
|
||||
Its purpose is to provide an L1 cache of Session objects.
|
||||
Having a working set of Session objects in memory allows multiple simultaneous requests for the same session to share the same Session object.
|
||||
|
||||
Jetty provides two (2) `SessionCache` implementations: the `DefaultSessionCache` and the `NullSessionCache`.
|
||||
The `DefaultSessionCache` retains Session objects in memory in a cache and has a number of link:#session-configuration-sessioncache[configuration options] to control cache behavior.
|
||||
It is the default that is used if no other `SessionCache` has been configured.
|
||||
It is suitable for non-clustered and clustered deployments with a sticky load balancer, as well as clustered deployments with a non-sticky load balancer, with some caveats.
|
||||
|
||||
The `NullSessionCache` does not actually cache any objects: each request uses a fresh Session object.
|
||||
It is suitable for clustered deployments without a sticky load balancer and non-clustered deployments when purely minimal support for sessions is needed.
|
||||
|
||||
`SessionCaches` always write out a Session to the `SessionDataStore` whenever the last request for the Session exits.
|
||||
|
||||
They can also be configured to do an immediate, eager write of a freshly created session.
|
||||
This can be useful if you are likely to experience multiple, near simultaneous requests referencing the same session, e.g. with HTTP/2 and you don't have a sticky load balancer.
|
||||
Alternatively, if the eager write is not done, application paths which create and then invalidate a session within a single request never incur the cost of writing to persistent storage.
|
||||
|
||||
Additionally, if the `EVICT_ON_INACTIVITY` eviction policy is in use, you can link:#session-configuration-sessioncache[configure] the `DefaultSessionCache` to force a write of the Session to the `SessionDataStore` just before the Session is evicted.
|
||||
|
||||
See link:#session-configuration-sessioncache[the L1 Session Cache] for more information.
|
||||
|
||||
==== SessionDataStore
|
||||
|
||||
There is one (1) `SessionDataStore` per context.
|
||||
Its purpose is to handle all persistence related operations on sessions.
|
||||
|
||||
The common characteristics for all `SessionDataStores` are whether or not they support passivation, and the length of the grace period.
|
||||
|
||||
Supporting passivation means that session data is serialized.
|
||||
Some persistence mechanisms serialize, such as JDBC, GCloud Datastore etc, whereas others may store an object in shared memory, e.g. Infinispan, when configured with a local cache.
|
||||
|
||||
Whether or not a clustering technology entails passivation controls whether or not the session passivation/activation listeners will be called.
|
||||
|
||||
The grace period is an interval, configured in seconds, that attempts to deal with the non-transactional nature of sessions with regard to finding sessions that have expired.
|
||||
Due to the lack of transactionality, in a clustered configuration, even with a sticky load balancer, it is always possible that a Session is live on a node but has not yet been updated in the persistent store.
|
||||
When `SessionDataStores` search their persistent store to find sessions that have expired, they typically perform a few sequential searches:
|
||||
|
||||
* The first verifies the expiration of a list of candidate session ids suggested by the SessionCache
|
||||
* The second finds sessions in the store that have expired which were last live on the current node
|
||||
* The third finds sessions that expired a "while" ago, irrespective of on which node they were last used: the definition of "a while" is based on the grace period.
|
||||
|
||||
Jetty instantiates the trivial `NullSessionDataStore` - which does not persist sessions - as the default.
|
||||
|
||||
The distribution provides a number of alternative `SessionDataStore` implementations such as link:#configuring-sessions-file-system[FileSessionDataStore], link:#configuring-sessions-gcloud[GCloudSessionDataStore], link:#configuring-sessions-jdbc[JDBCSessionDataStore], link:#configuring-sessions-mongodb[MongoSessionDataStore], link:#configuring-sessions-infinispan[InfinispanSessionDataStore], link:#configuring-sessions-hazelcast[HazelcastSessionDataStore].
|
||||
|
||||
|
||||
==== CachingSessionDataStore
|
||||
|
||||
The `CachingSessionDataStore` is a special type of `SessionDataStore` that inserts an L2 cache of Session data - the `SessionDataMap` - in front of a delegate `SessionDataStore`.
|
||||
The `SessionDataMap` is preferentially consulted before the actual SessionDataStore on reads.
|
||||
This can improve the performance of slow stores.
|
||||
|
||||
Jetty provides one implementation of the this L2 cache based on `Memcached`, the `MemcachedSessionDataMap`.
|
||||
|
||||
See link:#session-configuration-memcachedsessiondatastore[the L2 SessionData Cache]for additional information.
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[session-management]]
|
||||
== 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.
|
||||
Choosing the correct session manager implementation is an important consideration for every application as each can fit and perform optimally in different situations.
|
||||
|
||||
include::session-overview.adoc[]
|
||||
include::session-base.adoc[]
|
||||
include::session-sessioncache.adoc[]
|
||||
include::session-file-system.adoc[]
|
||||
include::session-jdbc.adoc[]
|
||||
include::session-mongodb.adoc[]
|
||||
include::session-infinispan.adoc[]
|
||||
include::session-hazelcast.adoc[]
|
||||
include::session-gcloud.adoc[]
|
||||
include::session-memcachedsessiondatastore.adoc[]
|
||||
include::session-usecases.adoc[]
|
|
@ -1,200 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[framework-weld]]
|
||||
=== Weld
|
||||
|
||||
http://seamframework.org/Weld[Weld] can be used to add support for CDI (Contexts and Dependency Injection) to Servlets, Listeners and Filters.
|
||||
It is easily configured with Jetty 9.
|
||||
|
||||
[[weld-setup-distro]]
|
||||
==== Weld Setup
|
||||
|
||||
The easiest way to configure weld is within the Jetty distribution itself.
|
||||
This can be accomplished either by enabling one of the startup link:#startup-modules[modules] described in link:#framework-cdi[CDI Framework]:
|
||||
|
||||
* the `cdi-decorate` module is the preferred Weld integration.
|
||||
The activation of this module by Weld can be confirmed by the following Weld log:
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters.
|
||||
....
|
||||
* the `cdi-spi` module works with Weld, but may restrict some non standard features.
|
||||
The activation of this module by Weld can be confirmed by the following Weld log:
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters.
|
||||
....
|
||||
* the deprecated `cdi2` module works with Weld prior to 3.1.2.Final.
|
||||
The activation of this module by Weld can be confirmed by the following Weld log:
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported.
|
||||
....
|
||||
|
||||
To activate the preferred `cdi-decorate` module use:
|
||||
-------------------------
|
||||
cd $JETTY_BASE
|
||||
java -jar $JETTY_HOME/start.jar --add-to-start=cdi-decorate
|
||||
-------------------------
|
||||
|
||||
____
|
||||
[TIP]
|
||||
For use with the jetty-maven-plugin, the best idea is to make the org.jboss.weld.servlet:weld-servlet and jetty-cdi artifacts _plugin_ dependencies (__not__ a webapp dependency).
|
||||
____
|
||||
|
||||
[[weld-embedded]]
|
||||
==== Weld with Embedded Jetty
|
||||
|
||||
When starting embedded Jetty programmatically from the `main` method it is necessary to:
|
||||
|
||||
* enable a jetty CDI integration mode by registering a `Listener` or `ServletContainerInitializer`
|
||||
|
||||
* enable Weld by registering either its `Listener` or `ServletContainerInitializer`
|
||||
|
||||
===== Using a `ServletContextHandler`
|
||||
|
||||
Embedded usage often uses a `ServletContextHandler` which is the base class of `WebappContext` and lacks the features of "web.xml" configuration and must be configured directly.
|
||||
The examples in this section based on a server and context set up as follows:
|
||||
|
||||
[source.JAVA, java]
|
||||
----
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Server jetty = new Server(8080);
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
context.addServlet(HelloWorldServlet.class, "/*");
|
||||
|
||||
/* CDI enabling goes here. See options below */
|
||||
|
||||
jetty.start();
|
||||
jetty.join();
|
||||
}
|
||||
|
||||
public static class HelloWorldServlet extends HttpServlet {
|
||||
|
||||
@Inject BeanManager manager;
|
||||
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/plain");
|
||||
resp.getWriter().append("Hello from " + manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
====== Initialize Weld with `ServletContainerInitializers`
|
||||
The best way to initialize both Jetty Weld integration is to use their respective `ServletContainerInitializers`:
|
||||
[source.JAVA, java]
|
||||
----
|
||||
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
|
||||
import org.eclipse.jetty.cdi.CdiDecoratingListener;
|
||||
import org.jboss.weld.environment.servlet.EnhancedListener;
|
||||
// ...
|
||||
context.setInitParameter(
|
||||
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
|
||||
CdiDecoratingListener.MODE);
|
||||
context.addBean(new ServletContextHandler.Initializer(context,
|
||||
new EnhancedListener()));
|
||||
context.addBean(new ServletContextHandler.Initializer(context,
|
||||
new CdiServletContainerInitializer()));
|
||||
----
|
||||
This code uses the `ServletContextHandler.Initializer` utility class added in Jetty-9.4.30.
|
||||
Prior to that the same effect can be achieved with a custom implementation of `ServletContextHandler.ServletContainerInitializerCaller`.
|
||||
|
||||
====== Initialize Weld with Listeners
|
||||
Jetty Weld integration can also be initialized by directly adding the listeners required:
|
||||
[source.JAVA, java]
|
||||
----
|
||||
import org.eclipse.jetty.cdi.CdiDecoratingListener;
|
||||
import org.jboss.weld.environment.servlet.Listener;
|
||||
// ...
|
||||
context.addEventListener(new CdiDecoratingListener(context));
|
||||
context.addEventListener(new Listener());
|
||||
----
|
||||
|
||||
====== Other Weld initializations
|
||||
When running embedded without a context classloader, it is not actually required to initialize Jetty at all.
|
||||
If just Weld is initialized then it will disover the Jetty APIs and use the deprecated integration:
|
||||
[source.JAVA, java]
|
||||
----
|
||||
import org.jboss.weld.environment.servlet.Listener;
|
||||
// ...
|
||||
context.addEventListener(new Listener());
|
||||
----
|
||||
However, this results in only a partially functional integration and the following warning:
|
||||
----
|
||||
INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported.
|
||||
----
|
||||
|
||||
Jetty can also be initialized by adding the `org.eclipse.jetty.webapp.DecoratingListener` listener instead of the `org.eclipse.jetty.cdi.CdiDecoratingListener`.
|
||||
However, this introduces a needless dependency on `jetty-webapp` and is not the preferred method.
|
||||
|
||||
====== Initialize Weld with `WebappContext`
|
||||
Some embedded usage still makes use of the `WebappContext` class for the convention-over-configuration benefits.
|
||||
The methods described for `ServletContextHandler` will work for `WebappContext`:
|
||||
|
||||
[source.JAVA, java]
|
||||
----
|
||||
import org.eclipse.jetty.cdi.CdiServletContainerInitializer;
|
||||
import org.eclipse.jetty.cdi.CdiDecoratingListener;
|
||||
import org.jboss.weld.environment.servlet.EnhancedListener;
|
||||
// ...
|
||||
Server server = new Server(8080);
|
||||
WebAppContext webapp = new WebAppContext();
|
||||
webapp.setContextPath("/");
|
||||
server.setHandler(webapp);
|
||||
|
||||
webapp.setInitParameter(
|
||||
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
|
||||
CdiDecoratingListener.MODE);
|
||||
webapp.addBean(new ServletContextHandler.Initializer(webapp,
|
||||
new CdiServletContainerInitializer()));
|
||||
webapp.addBean(new ServletContextHandler.Initializer(webapp,
|
||||
new EnhancedListener()));
|
||||
|
||||
// ...
|
||||
----
|
||||
|
||||
Alternately the webapp can be configured to discover the SCIs:
|
||||
|
||||
[source.JAVA, java]
|
||||
----
|
||||
Server server = new Server(8080);
|
||||
WebAppContext webapp = new WebAppContext();
|
||||
webapp.setContextPath("/");
|
||||
server.setHandler(webapp);
|
||||
|
||||
webapp.setInitParameter(
|
||||
CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE,
|
||||
CdiDecoratingListener.MODE);
|
||||
|
||||
// Need the AnnotationConfiguration to detect SCIs
|
||||
Configuration.ClassList.setServerDefault(server).addBefore(
|
||||
JettyWebXmlConfiguration.class.getName(),
|
||||
AnnotationConfiguration.class.getName());
|
||||
|
||||
// Need to expose our SCI class.
|
||||
webapp.getServerClasspathPattern().add("-" + CdiServletContainerInitializer.class.getName());
|
||||
webapp.getSystemClasspathPattern().add(CdiServletContainerInitializer.class.getName());
|
||||
|
||||
// ...
|
||||
----
|
|
@ -34,5 +34,6 @@ The Jetty server-side libraries provide:
|
|||
|
||||
include::http/server-http.adoc[]
|
||||
include::http2/server-http2.adoc[]
|
||||
include::sessions/sessions.adoc[]
|
||||
include::websocket/server-websocket.adoc[]
|
||||
include::server-io-arch.adoc[]
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-session-architecture]]
|
||||
|
||||
==== Session Architecture
|
||||
|
||||
===== Terminology
|
||||
|
||||
SessionIdManager:: is responsible for allocation of session ids
|
||||
HouseKeeper:: is responsible for orchestrating the detection and removal of expired sessions
|
||||
SessionHandler:: is responsible for managing the lifecycle of sessions within its associated context
|
||||
SessionCache:: is an L1 cache of in-use `Session` objects
|
||||
Session:: is a stateful object representing a `HttpSession`
|
||||
SessionData:: encapsulates the attributes and metadata associated with a `Session`
|
||||
SessionDataStore:: is responsible for creating, storing and reading `SessionData`
|
||||
CachingSessionDataStore:: is an L2 cache of `SessionData`
|
||||
|
||||
|
||||
Visually the session architecture can be represented like this:
|
||||
|
||||
[plantuml]
|
||||
----
|
||||
title Session Composition Diagram
|
||||
class Server
|
||||
|
||||
interface SessionIdManager
|
||||
|
||||
class HouseKeeper
|
||||
|
||||
class SessionHandler
|
||||
|
||||
interface SessionCache
|
||||
|
||||
interface SessionDataStore
|
||||
|
||||
class CachingSessionDataStore
|
||||
|
||||
class Session
|
||||
|
||||
class SessionData
|
||||
|
||||
Server "1" *-down- "1" SessionIdManager
|
||||
SessionIdManager "1" *-left- "1" HouseKeeper
|
||||
Server "1" *-down- "n" SessionHandler
|
||||
SessionHandler "1" *-down- "1" SessionCache
|
||||
SessionCache "1" *-down- "1" SessionDataStore
|
||||
SessionCache o-down- Session
|
||||
Session "1" *-- "1" SessionData
|
||||
SessionDataStore --> SessionData: CRUD
|
||||
SessionDataStore <|-- CachingSessionDataStore
|
||||
CachingSessionDataStore o- SessionData
|
||||
----
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-session-components]]
|
||||
==== Session Components
|
||||
|
||||
===== 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 link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionIdManager.html[DefaultSessionIdManager] - which should meet the needs of most users.
|
||||
If you do not explicitly configure a `SessionIdManager`, then when the `SessionHandler` starts, it will use an instance of the `DefaultSessionIdManager`.
|
||||
|
||||
====== Using the DefaultSessionIdManager
|
||||
|
||||
TODO
|
||||
- description of what the SessionHandler.doStart() does to create a DefaultSessionIdManager if none configured
|
||||
- code example of setting up the DefaultSessionIdManager
|
||||
|
||||
====== 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 the `Server` instance.
|
||||
The `workerName` becomes important in clustering scenarios because sessions can migrate from node to node: the `workerName` identifies which node was last managing a `Session`.
|
||||
* 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.
|
||||
|
||||
[[pg-server-session-housekeeper]]
|
||||
===== HouseKeeper
|
||||
|
||||
There is a maximum of one link:{JDURL}/org/eclipse/jetty/server/session/HouseKeeper.html[HouseKeeper] per `SessionIdManager`.
|
||||
Its purpose is to periodically poll the link:{JDURL}/org/eclipse/jetty/server/session/SessionHandler.html[SessionHandlers] to clean out expired sessions.
|
||||
This operation is usually referred to as "scavenging" expired sessions.
|
||||
|
||||
====== Using the HouseKeeper
|
||||
|
||||
TODO
|
||||
- description of the SessionHandler.doStart() creating a HouseKeeper
|
||||
- code example of setting up the HouseKeeper
|
||||
- configuring the scavenge interval
|
||||
|
||||
===== SessionCache
|
||||
|
||||
There is one `SessionCache` per `SessionHandler`, and thus one per context.
|
||||
Its purpose is to provide an L1 cache of `Session` objects.
|
||||
Having a working set of `Session` objects in memory allows multiple simultaneous requests for the same session to share the same `Session` object.
|
||||
A `SessionCache` uses a `SessionDataStore` to create, read, store and delete the `SessionData` associated with the `Session`.
|
||||
|
||||
Jetty provides two `SessionCache` implementations: the link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionCache.html[DefaultSessionCache] and the link:{JDURL}/org/eclipse/jetty/server/session/NullSessionCache.html[NullSessionCache].
|
||||
|
||||
====== Using the DefaultSessionCache
|
||||
The `DefaultSessionCache` retains `Session` objects in memory in a cache and has a number of configuration options to control cache behavior.
|
||||
It is suitable for non-clustered and clustered deployments with a sticky load balancer, as well as clustered deployments with a non-sticky load balancer, with some caveats.
|
||||
|
||||
====== Using the NullSessionCache
|
||||
The `NullSessionCache` does not actually cache any objects: each request uses a fresh `Session` object.
|
||||
It is suitable for clustered deployments without a sticky load balancer and non-clustered deployments when purely minimal support for sessions is needed.
|
||||
|
||||
``SessionCache``s always write out a Session to the link:{JDURL}/org/eclipse/jetty/server/session/SessionDataStore.html[SessionDataStore] whenever the last request for the `Session` exits.
|
||||
|
||||
They can also be configured to do an immediate, eager write of a freshly created session.
|
||||
This can be useful if you are likely to experience multiple, near simultaneous requests referencing the same session, e.g. with HTTP/2 and you don't have a sticky load balancer.
|
||||
Alternatively, if the eager write is not done, application paths which create and then invalidate a session within a single request never incur the cost of writing to persistent storage.
|
||||
|
||||
Additionally, if the `EVICT_ON_INACTIVITY` eviction policy is in use, you can xref:#pg-server-session-sessioncache[configure] the `DefaultSessionCache` to force a write of the `Session` to the `SessionDataStore` just before the `Session` is evicted.
|
||||
|
||||
See xref:pg-server-session-sessioncache[the L1 Session Cache] for more information.
|
||||
|
||||
===== SessionDataStore
|
||||
|
||||
There is one link:{JDURL}/org/eclipse/jetty/server/session/SessionDataStore.html[SessionDataStore] per `SessionCache`.
|
||||
Its purpose is to create, store, read and delete the `SessionData` related to a `Session`.
|
||||
The server libraries provide a number of alternative `SessionDataStore` implementations.
|
||||
|
||||
[plantuml]
|
||||
----
|
||||
title SessionDataStores
|
||||
|
||||
interface SessionDataStore
|
||||
class AbstractSessionDataStore
|
||||
class FileSessionDataStore
|
||||
class GCloudSessionDataStore
|
||||
class HazelcastSessionDataStore
|
||||
class InfinispanSessionDataStore
|
||||
class JDBCSessionDataStore
|
||||
class MongoSessionDataStore
|
||||
class CachingSessionDataStore
|
||||
|
||||
|
||||
SessionDataStore <|-- AbstractSessionDataStore
|
||||
AbstractSessionDataStore <|-- FileSessionDataStore
|
||||
AbstractSessionDataStore <|-- GCloudSessionDataStore
|
||||
AbstractSessionDataStore <|-- HazelcastSessionDataStore
|
||||
AbstractSessionDataStore <|-- InfinispanSessionDataStore
|
||||
AbstractSessionDataStore <|-- JDBCSessionDataStore
|
||||
AbstractSessionDataStore <|-- MongoSessionDataStore
|
||||
SessionDataStore <|-- CachingSessionDataStore
|
||||
----
|
||||
|
||||
The `AbstractSessionDataStore` provides most of the behaviour common to ``SessionDataStore``s.
|
||||
The common characteristics for all ``SessionDataStore``s that derive from `AbstractSessionDataStore` are:
|
||||
|
||||
passivation::
|
||||
Supporting passivation means that session data is serialized.
|
||||
Some persistence mechanisms serialize, such as JDBC, GCloud Datastore etc.
|
||||
Others store an object in shared memory, e.g. Infinispan.
|
||||
Whether or not a clustering technology entails passivation controls whether or not ``HttpSessionActivationListener``s will be called.
|
||||
When implementing a custom `SessionDataStore` you need to decide whether or not passivation will be supported.
|
||||
savePeriod::
|
||||
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 a `Session`, the `SessionData` for that `Session` is always persisted, even if the only thing that changed is the `lastAccessTime`.
|
||||
If the `savePeriod` is non-zero, the `SessionData` will not be persisted if no session attributes changed, unless the time since the last save exceeds the `savePeriod`.
|
||||
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.
|
||||
gracePeriod::
|
||||
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.
|
||||
Because the servlet api does not define session transactions, 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 the `gracePeriod` to provide a bit of leeway around the moment of expiry.
|
||||
The `AbstraceSessionDataStore` uses the `gracePeriod` in the following manner to help xref:pg-server-session-housekeeper[scavenge] expired sessions:
|
||||
|
||||
* on every scavenge cycle it searches for sessions that belong to our context that expired at least one `gracePeriod` ago
|
||||
* infrequently we also do a scan to find and summarily delete sessions - from any context - that expired at least 10 `gracePeriod``s ago
|
||||
|
||||
The trivial link:{JDURL}/org/eclipse/jetty/server/session/NullSessionDataStore.html[NullSessionDataStore] - which does not persist sessions - is the default used by the `SessionHandler`.
|
||||
|
||||
===== CachingSessionDataStore
|
||||
[plantuml]
|
||||
----
|
||||
interface SessionDataMap
|
||||
class CachingSessionDataStore
|
||||
interface SessionDataStore
|
||||
|
||||
CachingSessionDataStore "1" *-down- "1" SessionDataMap
|
||||
CachingSessionDataStore "`" *-down- "1" SessionDataStore
|
||||
----
|
||||
|
||||
The `CachingSessionDataStore` is a special type of `SessionDataStore` that acts as an L2 cache for `SessionData`.
|
||||
It has 2 components: the cache, and the actual backing `SessionDataStore`.
|
||||
The cache is an instance of a link:{JDURL}/org/eclipse/jetty/server/session/SessionDataMap.html[SessionDataMap].
|
||||
The `CachingSessionDataStore` consults this cache before consulting the actual `SessionDataStore`.
|
||||
Using a cache for the `SessionData` can improve the performance of slow stores.
|
||||
|
||||
Jetty provides one implementation of this L2 cache based on `Memcached`, link:{JDURL}/org/eclipse/jetty/memcached/session/MemcachedSessionDataMap.html[MemcachedSessionDataMap].
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
[[pg-server-session]]
|
||||
=== 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.
|
||||
|
||||
include::session-architecture.adoc[]
|
||||
include::session-components.adoc[]
|
||||
|
||||
|
Loading…
Reference in New Issue