Update session docs.
Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
parent
227f91cdfb
commit
b5aa128a36
|
@ -43,7 +43,7 @@ IMPORTANT: If you have more than one Jetty instance, it is *crucial* that you co
|
||||||
|
|
||||||
jetty.sessionScavengeInterval.seconds::
|
jetty.sessionScavengeInterval.seconds::
|
||||||
This is the period in _seconds_ between runs of the `HouseKeeper`, responsible for orchestrating the removal of expired sessions.
|
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).
|
By default it will run appproximately every 600 secs (ie 10 mins).
|
||||||
As a rule of thumb, you should ensure that the xref:ops-session-base-scavenge[scavenge] interval is shorter than the `<session-timeout>` of your sessions to ensure that they are promptly scavenged.
|
As a rule of thumb, you should ensure that the xref:ops-session-base-scavenge[scavenge] interval is shorter than the `<session-timeout>` of your sessions to ensure that they are promptly scavenged.
|
||||||
On the other hand, if you have a backend store configured for your sessions, xref:ops-session-base-scavenge[scavenging] too frequently can increase the load on it.
|
On the other hand, if you have a backend store configured for your sessions, xref:ops-session-base-scavenge[scavenging] too frequently can increase the load on it.
|
||||||
|
|
||||||
|
@ -53,7 +53,13 @@ TIP: Don't forget that the `<session-timeout>` is specified in web.xml in _minut
|
||||||
==== Session Scavenging
|
==== Session Scavenging
|
||||||
|
|
||||||
The `HouseKeeper` is responsible for the periodic initiation of session scavenge cycles.
|
The `HouseKeeper` is responsible for the periodic initiation of session scavenge cycles.
|
||||||
The `jetty.sessionScavengeInterval.seconds` property in `start.d/sessions.ini` controls the periodicity of the cycle.
|
The `jetty.sessionScavengeInterval.seconds` property in `$jetty.base/start.d/sessions.ini` controls the periodicity of the cycle.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
The HouseKeeper semi-randomly adds an additional 10% to the configured `sessionScavengeInterval`.
|
||||||
|
This is to prevent multiple nodes in a cluster that are all started at once from syncing up scavenge cycles and placing extra load on the configured persistence mechanism.
|
||||||
|
====
|
||||||
|
|
||||||
A session whose expiry time has been exceeded is considered eligible for scavenging.
|
A session whose expiry time has been exceeded is considered eligible for scavenging.
|
||||||
The session might be present in a `SessionCache` and/or present in the session persistence/clustering mechanism.
|
The session might be present in a `SessionCache` and/or present in the session persistence/clustering mechanism.
|
||||||
|
|
|
@ -31,8 +31,7 @@ SessionData:: encapsulates the attributes and metadata associated with a `Sessio
|
||||||
SessionDataStore:: is responsible for creating, storing and reading `SessionData`
|
SessionDataStore:: is responsible for creating, storing and reading `SessionData`
|
||||||
CachingSessionDataStore:: is an L2 cache of `SessionData`
|
CachingSessionDataStore:: is an L2 cache of `SessionData`
|
||||||
|
|
||||||
|
The session architecture can be represented like so:
|
||||||
Visually the session architecture can be represented like this:
|
|
||||||
|
|
||||||
[plantuml]
|
[plantuml]
|
||||||
----
|
----
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// 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-sessioncache]]
|
||||||
|
==== Session Components: The 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].
|
||||||
|
|
||||||
|
[[pg-server-session-hash]]
|
||||||
|
===== 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.
|
||||||
|
|
||||||
|
[[pg-server-session-null]]
|
||||||
|
===== 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.
|
|
@ -16,79 +16,8 @@
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
//
|
//
|
||||||
|
|
||||||
[[pg-server-session-components]]
|
[[pg-server-session-sessiondatastore]]
|
||||||
==== Session Components
|
==== Session Components: The SessionDataStore
|
||||||
|
|
||||||
===== 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`.
|
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`.
|
Its purpose is to create, store, read and delete the `SessionData` related to a `Session`.
|
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// 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-sessionidmgr]]
|
||||||
|
==== Session Components: The SessionIdManager
|
||||||
|
|
||||||
|
There is a maximum of one `SessionIdManager` per `Server` instance.
|
||||||
|
Its purpose is to generate fresh, unique session ids and to coordinate the re-use of session ids amongst co-operating contexts.
|
||||||
|
|
||||||
|
The `SessionIdManager` is agnostic with respect to the type of clustering technology chosen.
|
||||||
|
|
||||||
|
Jetty provides a default implementation - the 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`.
|
||||||
|
|
||||||
|
[[pg-server-session-defaultidmgr]]
|
||||||
|
===== The DefaultSessionIdManager
|
||||||
|
|
||||||
|
At startup, if no instance of the `HouseKeeper` has been explicitly set, the `DefaultSessionIdManager` will create one.
|
||||||
|
|
||||||
|
Also at startup, the `workerName` is determined.
|
||||||
|
The `workerName` must be unique per `Server`, and identifies the server in a cluster.
|
||||||
|
If a `workerName` has not been explicitly set, then the value is derived as follows:
|
||||||
|
|
||||||
|
+node[JETTY_WORKER_NAME]+
|
||||||
|
|
||||||
|
where `JETTY_WORKER_NAME` is an environment variable whose value can be an integer or string.
|
||||||
|
If the environment variable is not set, then it defaults to `0`, yielding the default `workerName` of `"node0"`.
|
||||||
|
|
||||||
|
The `DefaultSessionIdManager` uses `SecureRandom` to generate unique session ids.
|
||||||
|
|
||||||
|
The `SessionHandler` class, which is used by both the `ServletContextHandler` and the `WebAppContext` classes, will instantiate a `DefaultSessionIdManager` on startup if it does not detect one already present for the `Server`.
|
||||||
|
|
||||||
|
Here is an example of explicitly setting up a `DefaultSessionIdManager` in code:
|
||||||
|
|
||||||
|
[source,java,indent=0]
|
||||||
|
----
|
||||||
|
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/session/SessionDocs.java[tags=default]
|
||||||
|
----
|
||||||
|
|
||||||
|
===== 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]]
|
||||||
|
===== Session Components: The 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.
|
||||||
|
The scavenging interval is configured by the `setIntervalSec(long)` method.
|
||||||
|
The default value is ``600``sec, ie ``10``mins.
|
||||||
|
|
||||||
|
[IMPORTANT]
|
||||||
|
====
|
||||||
|
The HouseKeeper semi-randomly adds an additional `10%` of the configured `intervalSec`.
|
||||||
|
This is to help prevent sync-ing up of servers in a cluster that are all restarted at once, and slightly stagger their scavenge cycles to ensure any load on the persistent storage mechanism is spread out.
|
||||||
|
====
|
||||||
|
|
||||||
|
This code example shows how to configure a `HouseKeeper`, along with a `DefaultSessionIdManager`:
|
||||||
|
|
||||||
|
[source,java,indent=0]
|
||||||
|
----
|
||||||
|
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/session/SessionDocs.java[tags=housekeeper]
|
||||||
|
----
|
|
@ -22,6 +22,6 @@
|
||||||
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.
|
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-architecture.adoc[]
|
||||||
include::session-components.adoc[]
|
include::session-sessionidmgr.adoc[]
|
||||||
|
include::session-sessioncache.adoc[]
|
||||||
|
include::session-sessiondatastore.adoc[]
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// 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
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.docs.programming.server.session;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.session.DefaultSessionIdManager;
|
||||||
|
import org.eclipse.jetty.server.session.HouseKeeper;
|
||||||
|
|
||||||
|
public class SessionDocs
|
||||||
|
{
|
||||||
|
public void minimumDefaultSessionIdManager()
|
||||||
|
{
|
||||||
|
//tag::default[]
|
||||||
|
Server server = new Server();
|
||||||
|
DefaultSessionIdManager idMgr = new DefaultSessionIdManager(server);
|
||||||
|
//you must set the workerName unless you set the env viable JETTY_WORKER_NAME
|
||||||
|
idMgr.setWorkerName("3");
|
||||||
|
server.setSessionIdManager(idMgr);
|
||||||
|
//end::default[]
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defaultSessionIdManagerWithHouseKeeper()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//tag::housekeeper[]
|
||||||
|
Server server = new Server();
|
||||||
|
DefaultSessionIdManager idMgr = new DefaultSessionIdManager(server);
|
||||||
|
idMgr.setWorkerName("7");
|
||||||
|
server.setSessionIdManager(idMgr);
|
||||||
|
|
||||||
|
HouseKeeper houseKeeper = new HouseKeeper();
|
||||||
|
houseKeeper.setSessionIdManager(idMgr);
|
||||||
|
//set the frequency of scavenge cycles
|
||||||
|
houseKeeper.setIntervalSec(600L);
|
||||||
|
idMgr.setSessionHouseKeeper(houseKeeper);
|
||||||
|
//end::housekeeper[]
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue