Update session docs.

Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2020-09-14 16:42:30 +02:00
parent 227f91cdfb
commit b5aa128a36
7 changed files with 208 additions and 80 deletions

View File

@ -43,7 +43,7 @@ IMPORTANT: If you have more than one Jetty instance, it is *crucial* that you co
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).
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.
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
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.
The session might be present in a `SessionCache` and/or present in the session persistence/clustering mechanism.

View File

@ -31,8 +31,7 @@ SessionData:: encapsulates the attributes and metadata associated with a `Sessio
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:
The session architecture can be represented like so:
[plantuml]
----

View File

@ -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.

View File

@ -16,79 +16,8 @@
// ========================================================================
//
[[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
[[pg-server-session-sessiondatastore]]
==== Session Components: The 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`.

View File

@ -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]
----

View File

@ -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.
include::session-architecture.adoc[]
include::session-components.adoc[]
include::session-sessionidmgr.adoc[]
include::session-sessioncache.adoc[]
include::session-sessiondatastore.adoc[]

View File

@ -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();
}
}
}