Session doc updates.
Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
parent
4d992a4315
commit
8b53c386b1
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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-cachingsessiondatastore]]
|
||||
==== Session Components: The 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].
|
||||
|
|
@ -23,15 +23,20 @@ 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`.
|
||||
``SessionCache``s can be created by `SessionHandlers` as needed via a `SessionCacheFactory` registered as a bean on the `Server`.
|
||||
Alternatively, you can construct and configure an instance of a `SessionCache` and explicitly set it on a `SessionHander`.
|
||||
Be aware that in this case, you must _also_ ensure your instance is set up with a `SessionDataStore`.
|
||||
If instead the `SessionHandler` uses the `SessionCacheFactory` to create a `SessionCache` instance, it will be responsible for choosing a `SessionDataStore`: if a `SessionDataStoreFactory` bean is found on the `Server` instance, it will use that; otherwise it uses the `NullSessionDataStore`.
|
||||
More on ``SessionDataStore``s later, in this section we will concentrate the `SessionCache`.
|
||||
|
||||
There are two ways to create a `SessionCache` for a `SessionHandler`:
|
||||
|
||||
. allow the `SessionHandler` to create one lazily at startup
|
||||
The `SessionHandler` looks for a `SessionCacheFactory` bean on the server to produce the `SessionCache` instance.
|
||||
It then looks for a `SessionDataStoreFactory` bean on the server to produce a `SessionDataStore` instance to use with the `SessionCache`.
|
||||
. pass a fully configured `SessionCache` instance to the `SessionHandler`
|
||||
You are responsible for configuring both the `SessionCache` instance and its `SessionDataStore`
|
||||
|
||||
More on ``SessionDataStore``s xref:pg-server-session-sessiondatastore[later], in this section we will concentrate on the `SessionCache` and `SessionCacheFactory`.
|
||||
|
||||
|
||||
The link:{JDURL}/org/eclipse/jetty/server/session/AbstractSessionCache.html[AbstractSessionCache] provides most of the behaviour of ``SessionCache``s.
|
||||
If you are implementing a custom `SessionCache` we recommend you extend this base class, as the Servlet Specification has many subtleties and extending the base class ensures that your implementation will take account of them.
|
||||
If you are implementing a custom `SessionCache` we strongly recommend you extend this base class, as the Servlet Specification has many subtleties and extending the base class ensures that your implementation will take account of them.
|
||||
|
||||
Some of the important behaviours of ``SessionCache``s are:
|
||||
|
||||
|
@ -51,7 +56,7 @@ The eviction strategies are:
|
|||
saveOnInactiveEviction::
|
||||
This controls whether a session will be persisted to the `SessionDataStore` if it is being evicted due to the EVICT_ON_INACTIVITY policy.
|
||||
Usually sessions are written to the `SessionDataStore` whenever the last simultaneous request exits the session.
|
||||
However, as `SessionDataStores` can be configured to xref:pg-server-session-sessiondatastore[skip some writes], this option ensures that the session will be written out.
|
||||
However, as `SessionDataStores` can be configured to xref:pg-server-session-sessiondatastore-skip[skip some writes], this option ensures that the session will be written out.
|
||||
|
||||
saveOnCreate::
|
||||
Usually a session will be written through to the configured `SessionDataStore` when the last request for it finishes.
|
||||
|
@ -99,14 +104,16 @@ The link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionCache.html#getSe
|
|||
reset::
|
||||
The link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionCache.html#resetStats()[DefaultSessionCache.resetStats()] zeros out the statistics counters.
|
||||
|
||||
As a convenience, you can use the link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionCacheFactory.html[DefaultSessionFactory] to create a `DefaultSessionCache` whenever a new `SessionHandler` is started.
|
||||
If you create a link:{JDURL}/org/eclipse/jetty/server/session/DefaultSessionCacheFactory.html[DefaultSessionFactory] and register it as `Server` bean, a `SessionHandler` will be able to lazily create a `DefaultSessionCache`.
|
||||
The `DefaultSessionCacheFactory` has all of the same configuration setters as a `DefaultSessionCache`.
|
||||
Alternatively, if you only have a single `SessionHandler`, or you need to configure a `DefaultSessionCache` differently for every `SessionHandler`, then you could dispense with the `DefaultSessionCacheFactory` and simply instantiate, configure and pass in the `DefaultSessionCache` yourself.
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/session/SessionDocs.java[tags=defaultsessioncache]
|
||||
----
|
||||
|
||||
NOTE:: If you don't configure any `SessionCache` or `SessionCacheFactory`, the `SessionHandler` will automatically use a `DefaultSessionCache`.
|
||||
NOTE:: If you don't configure any `SessionCache` or `SessionCacheFactory`, the `SessionHandler` will automatically create a `DefaultSessionCache`.
|
||||
|
||||
[[pg-server-session-null]]
|
||||
===== The NullSessionCache
|
||||
|
@ -115,6 +122,11 @@ It is suitable for clustered deployments without a sticky load balancer and non-
|
|||
|
||||
As no sessions are actually cached, of course functions like `invalidateOnShutdown` and all of the eviction strategies have no meaning for the `NullSessionCache`.
|
||||
|
||||
There is a `NullSessionCacheFactory` which you can instantiate, configure and set as a `Server` bean to enable the `SessionHandler` to automatically create new ``NullCache``s as needed.
|
||||
All of the same configuration options are available on the `NullSessionCacheFactory` as the `NullSessionCache` itself.
|
||||
Alternatively, if you only have a single `SessionHandler`, or you need to configure a `NullSessionCache` differently for every `SessionHandler`, then you could dispense with the `NullSessionCacheFactory` and simply instantiate, configure and pass in the `NullSessionCache` yourself.
|
||||
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/session/SessionDocs.java[tags=nullsessioncache]
|
||||
|
@ -123,15 +135,15 @@ include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/session/Sess
|
|||
[[pg-server-session-customcache]]
|
||||
===== Implementing a Custom SessionCache
|
||||
|
||||
As previously mentioned, the best thing to do is to extend the `AbstractSessionCache`.
|
||||
As previously mentioned, we highly recommend that you extend the link:{JDURL}/org/eclipse/jetty/server/session/AbstractSessionCache.html[AbstractSessionCache].
|
||||
|
||||
===== Heterogenous Caching
|
||||
|
||||
Using the `DefaultSessionCacheFactory` or the `NullSessionCacheFactory` will ensure that every time a `SessionHandler` starts, by default it will create a new instance of the corresponding type of `SessionCache`.
|
||||
Using one of the s`SessionCacheFactory``s will ensure that every time a `SessionHandler` starts it will create a new instance of the corresponding type of `SessionCache`.
|
||||
|
||||
But, what if you deploy multiple webapps, and for one of them, you don't want to use sessions?
|
||||
Or alternatively, you don't want to use sessions, but you have one webapp that now needs them?
|
||||
In that case, you can configure the factory appropriate to the majority, and then specifically create the right type of cache for the others.
|
||||
In that case, you can configure the `SessionCacheFactory` appropriate to the majority, and then specifically create the right type of `SessionCache` for the others.
|
||||
Here's an example where we configure the `DefaultSessionCacheFactory` to handle most webapps, but then specifically use a `NullSessionCache` for another:
|
||||
|
||||
[source,java,indent=0]
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
[[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`.
|
||||
A link:{JDURL}/org/eclipse/jetty/server/session/SessionDataStore.html[SessionDataStore] mediates the storage, retrieval and deletion of `SessionData`.
|
||||
There is one `SessionDataStore` per `SessionCache`.
|
||||
The server libraries provide a number of alternative `SessionDataStore` implementations.
|
||||
|
||||
[plantuml]
|
||||
|
@ -48,50 +48,32 @@ 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:
|
||||
The link:{JDURL}/org/eclipse/jetty/server/session/AbstractSessionDataStore.html[AbstractSessionDataStore] provides most of the behaviour common to ``SessionDataStore``s:
|
||||
|
||||
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.
|
||||
Others store an object in shared memory, e.g. Infinispan and thus don't serialize session data.
|
||||
Whether or not a persistence 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.
|
||||
|
||||
[[pg-server-session-sessiondata-skip]]
|
||||
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`.
|
||||
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.
|
||||
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:
|
||||
Thus, we use the `gracePeriod` to provide a bit of leeway around the moment of expiry during xref:pg-server-session-housekeeper[scavenge]:
|
||||
|
||||
* 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
|
||||
* on every xref:pg-server-session-housekeeper[scavenge] cycle an `AbstractSessionDataStore` searches for sessions that belong to the context that expired at least one `gracePeriod` ago
|
||||
* infrequently the `AbstractSessionDataStore` searches for and summarily deletes 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].
|
||||
NOTE:: The trivial link:{JDURL}/org/eclipse/jetty/server/session/NullSessionDataStore.html[NullSessionDataStore] - which does not persist sessions - is the default used by the `SessionHandler`.
|
||||
|
||||
|
|
|
@ -20,49 +20,140 @@
|
|||
==== Session Components: The SessionHandler
|
||||
|
||||
Each context can have a single `SessionHandler`.
|
||||
The purpose of the `SessionHandler` is to interact with the `Request` and `Response` to create, maintain and propagate sessions
|
||||
The purpose of the `SessionHandler` is to interact with the `Request` and `Response` to create, maintain and propagate sessions.
|
||||
It also calls the context-level session listeners at appropriate points in the session lifecycle.
|
||||
|
||||
===== Configuration =====
|
||||
|
||||
The majority of configuration for the `SessionHandler` can be done via `web.xml` `<session-config>` declarations, or the `javax.servlet.SessionCookieConfig` api.
|
||||
There are also a few jetty-specific configuration options that we will cover here:
|
||||
|
||||
checkingRemoteSessionIdEncoding::
|
||||
Boolean, default `false`.
|
||||
This controls whether or not the `javax.servlet.http.Response.encodeURL(String)` method will include the session id as a path parameter when the URL is destined for a remote node.
|
||||
|
||||
This can also be configured by:
|
||||
* setting the `org.eclipse.jetty.servlet.CheckingRemoteSessionIdEncoding` context init paramter
|
||||
|
||||
setMaxInactiveInterval::
|
||||
Integer, seconds.
|
||||
This is equivalent to the `<session-config><session-timeout/></session-config>` that can be set in `web.xml`, although take note that that in `web.xml` this is specified in _minutes_ but this method uses _seconds_.
|
||||
This is the amount of time after which an unused session may be scavenged.
|
||||
This can also be configured by:
|
||||
|
||||
* defining the `<session-config><session-timeout/></session-config>` element in `web.xml`, although take note that this element is specified in _minutes_ but this method uses _seconds_.
|
||||
* calling the `javax.servlet.ServletContext.setSessionTimeout(int)` method, where the timeout is configured in _minutes_.
|
||||
|
||||
setHttpOnly::
|
||||
Boolean, default `false`.
|
||||
This is equivalent to using `javax.servlet.SessionCookieConfig.setHttpOnly(boolean)` method, or the `<session-config><cookie-config><http-only/></cookie-config></session-config>` element.
|
||||
If `true`, the session cookie will not be exposed to client-side scripting code.
|
||||
This can also be configured by:
|
||||
|
||||
* using `javax.servlet.SessionCookieConfig.setHttpOnly(boolean)` method
|
||||
* defining the `<session-config><cookie-config><http-only/></cookie-config></session-config>` element in `web.xml`
|
||||
|
||||
[[pg-server-session-refreshcookie]]
|
||||
refreshCookieAge::
|
||||
Integer, seconds, default is `-1`.
|
||||
This controls resetting the session cookie when `SessionCookieConfig.setMaxAge(int)` is non-zero.
|
||||
See also xref:pg-server-session-maxAge[setting the max session cookie age with an init parameter].
|
||||
If the amount of time since the session cookie was last set exceeds this time, the session cookie is regenerated to keep the session cookie valid.
|
||||
|
||||
sameSite::
|
||||
`HttpCookie.SameSite`, default `null`.
|
||||
The values are `HttpCookie.SameSite.NONE`, `HttpCookie.SameSite.STRICT`, `HttpCookie.SameSite.LAX`.
|
||||
|
||||
secureRequestOnly::
|
||||
Boolean, default true.
|
||||
Boolean, default `true`.
|
||||
If `true` and the request is HTTPS, the set session cookie will be marked as `secure`, meaning the client will only send the session cookie to the server on subsequent requests over HTTPS.
|
||||
This can also be configured by:
|
||||
|
||||
* using the `javax.servlet.SessionCookieConfig.setSecure(true)` method, in which case the set session cookie will _always_ be marked as `secure`, even if the request triggering the creation of the cookie was not over HTTPS.
|
||||
|
||||
sessionCookie::
|
||||
String, default is `JSESSIONID`.
|
||||
This is the name of the session cookie.
|
||||
It can alternatively be configured by:
|
||||
|
||||
* using `javax.servlet.SessionCookieConfig.setName(String)` method
|
||||
* setting the `org.eclipse.jetty.servlet.SessionCookie` context init parameter.
|
||||
|
||||
sessionIdPathParameterName::
|
||||
String, default is `jsessionid`.
|
||||
This is the name of the path parameter used to transmit the session id on request URLs, and on encoded URLS in responses.
|
||||
It can alternatively be configured by:
|
||||
|
||||
* setting the `org.eclipse.jetty.servlet.SessionIdPathParameterName` context init parameter
|
||||
|
||||
|
||||
sessionTrackingModes::
|
||||
`Set<javax.servlet.SessionTrackingMode>`.
|
||||
Default is `SessionTrackingMode.COOKIE`, `SessionTrackingMode.URL`.
|
||||
This can also be configured by:
|
||||
|
||||
* using the `setSessionTrackingModes(Set<javax.servlet.SessionTrackingMode>)` method
|
||||
* using the `javax.servlet.ServletContext.setSessionTrackingModes<Set<javax.servlet.SessionTrackingMode>)` method
|
||||
* defining up to three ``<tracking-mode>``s for the `<session-config>` element in `web.xml`
|
||||
|
||||
usingCookies::
|
||||
Boolean, default `true`.
|
||||
Determines whether or not the `SessionHandler` will look for session cookies on requests, and will set session cookies on responses.
|
||||
If `false` session ids must be transmitted as path params on URLs.
|
||||
This can also be configured by:
|
||||
|
||||
* using the `setSessionTrackingModes(Set<javax.servlet.SessionTrackingMode>)` method
|
||||
* using the `javax.servlet.ServletContext.setSessionTrackingModes<Set<javax.servlet.SessionTrackingMode>)` method
|
||||
|
||||
|
||||
There are also a few session settings that do not have SessionHandler setters, but can be configured with context init parameters:
|
||||
|
||||
[[pg-server-session-maxAge]]
|
||||
org.eclipse.jetty.servlet.MaxAge::
|
||||
This is the maximum number of seconds that the session cookie will be considered to be valid.
|
||||
By default, the cookie has no maximum validity time.
|
||||
See also xref:pg-server-session-refreshcookie[refreshing the session cookie].
|
||||
The value can also be configured by:
|
||||
|
||||
* calling the `SessionCookieConfig.setMaxAge(int)` method.
|
||||
|
||||
|
||||
org.eclipse.jetty.servlet.SessionDomain::
|
||||
String, default `null`.
|
||||
This is the domain of the session cookie.
|
||||
This can also be configured by:
|
||||
|
||||
* using the `javax.servlet.SessionCookieConfig.setDomain(String)` method
|
||||
* defining the `<session-config><cookie-config><domain/></cookie-config></session-config>` element in `web.xml`
|
||||
|
||||
|
||||
org.eclipse.jetty.servlet.SessionPath::
|
||||
String, default `null`.
|
||||
This is used when creating a new session cookie.
|
||||
If nothing is configured, the context path is used instead, defaulting to `/`.
|
||||
This can also be configured by:
|
||||
|
||||
* using the `javax.servlet.SessionCookieConfig.setPath(String)` method
|
||||
* defining the `<session-config><cookie-config><path/></cookie-config></session-config>` element in `web.xml`
|
||||
|
||||
===== Statistics =====
|
||||
|
||||
Some statistics about the sessions for a context can be obtained from the `SessionHandler`, either by calling the methods directly or via `jmx`:
|
||||
|
||||
sessionsCreated::
|
||||
This is the total number of sessions that have been created for this context since Jetty started.
|
||||
|
||||
sessionTimeMax::
|
||||
The longest period of time a session was valid in this context before being invalidated.
|
||||
|
||||
sessionTimeMean::
|
||||
The average period of time a session in this context was valid.
|
||||
|
||||
sessionTimeStdDev::
|
||||
The standard deviation of the session validity times for this context.
|
||||
|
||||
sessionTimeTotal::
|
||||
The total time that all sessions in this context have remained valid.
|
||||
|
||||
You can reset the statistics counters by either calling the following method directly on the the `SessionHandler`, or using `jmx`:
|
||||
|
||||
statsReset::
|
||||
Resets the `SessionHandler` statistics counters.
|
||||
|
||||
|
|
|
@ -25,3 +25,4 @@ include::session-architecture.adoc[]
|
|||
include::session-sessionidmgr.adoc[]
|
||||
include::session-sessioncache.adoc[]
|
||||
include::session-sessiondatastore.adoc[]
|
||||
include::session-cachingsessiondatastore.adoc[]
|
Loading…
Reference in New Issue