tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <>
Subject Re: mod_jk and session stickiness
Date Wed, 23 Jul 2014 15:59:58 GMT
Hash: SHA256


On 7/23/14, 11:23 AM, Rainer Jung wrote:
> On 23.07.2014 16:37, Christopher Schultz wrote:
>> On 7/18/14, 12:13 PM, Rainer Jung wrote:
>>> On 17.06.2014 16:43, Christopher Schultz wrote:
>>>> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
>>>> All,
>>>> I've been using sticky sessions with mod_jk and I can see
>>>> that there is a bit of a problem when attempting to take a
>>>> backend Tomcat server out of load-balanced rotation: a user
>>>> who never (or rarely) restarts their web browser will keep
>>>> the same JSESSIONID cookie forever and therefore end up with
>>>> the same backend server whether it has been disabled or not.
>>>> Quick series of events:
>>>> 1. User visits load-balancer and gets a randomly-assigned 
>>>> backend server/route. We'll call this route "X". The
>>>> JSESSIONID cookie set by the backend server is therefore
>>>> foo.X.
>>>> 2. User's requests are routed by mod_jk to route X.
>>>> 3. Route X is disabled using mod_jk's status worker
>>>> 4. User's session on server X expires.
>>>> [Technically, 3 and 4 can happen in either order]
>>>> 5. User makes a new request to the load-balancer, and mod_jk
>>>> sees the JSESSIONID cookie still set to foo.X. mod_jk sends
>>>> the request to route X which allows the user to login, etc.
>>>> Thus, it takes more time than necessary to bleed all the
>>>> traffic from route X for maintenance, etc.
>>>> Is there a way for mod_jk to ask route X if the session is 
>>>> *still* valid? It seems that mod_jk will not re-route a
>>>> request that looks like it's got a valid session id to a new
>>>> (active) backend server unless the backend server X is
>>>> actually down.
>>>> Any ideas?
>>> Not exactly what you want, but you can build something around
>>> it:
>>> 1) Switch off stickyness for specific URLs
>>> If you know that users will come via specific URLs, like a
>>> login page, and you want that page to be handled non-sticky to
>>> optimize load balancing even if users have an old cookie, you
>>> can do that by setting the Apache envvar JK_STICKY_IGNORE. Look
>>> for JK_STICKY_IGNORE on:
>> This seems like a reasonable way to do things, except that we
>> still want to support requests to protected resources being saved
>> and redirected to the login page. If we did this
>> (JK_STICKY_IGNORE), then we'd end up "forgetting" the saved
>> request (because the client would be re-balanced to another node
>> for the login page) and ending up with a (useless) session on the
>> node we are trying to take down.
>> We'd like to retain the request-saving capabilities of the
>> container.
> Whatever "saved" exactly means: if you can identify that situation
> in terms of any part of the request (e.g. something in the referer
> header etc.), you can add that as a positive or negative condition
> via RewriteCond (or the 2.4 unified expression parser) and set 
> JK_STICKY_IGNORE in a RewriteRule that does not change the URI,
> only sets the variable and also only of the RewriteConds apply.
> You'd have to analyze the request-response stream e.g. with a
> browser plugin to look for a useful header or similar which can be
> used to distinguish the "saved" and the "normal" case.

When I say "saved" I mean this workflow:

1. User requests a protected resource
2. Container saves the request (which creates a new session), presents
the login screen
3. User authenticates
4. User is redirected to request saved in step #1

>> One option we have here is to provide separate URLs for
>> "regular" logins versus the saved-request logins mentioned above:
>> that would probably solve both problems.
>>> 2) Improve handling of sessions for node with activation 
>>> "disabled"
>>> If you switch a node to activation "disabled", mod_jk will not 
>>> send requests there, that have no session id (and of course
>>> also not when the session route points to another node). But
>>> the old cookie requests might still go there.
>> Yes, this is what we would normally do.
>>> For that you can use the feature, that mod_jk forwards the 
>>> activation state to the Tomcat node. The node can then decide
>>> on itself, whether it will handle a request coming in with an
>>> invalid session id, or for example clears the session cookie
>>> and does a self-referential redirect, which then by mod_jk is
>>> balanced on the fully enabled nodes.
>> This sounds like a promising technique. I was thinking we'd just
>> tell the Tomcat node directly (e.g. set a context-scoped flag)
>> that it was "disabled", but having AJP forward that information
>> would be even better, so the state can be managed entirely by the
>> status worker on the httpd side.
>>> This logic can be put into a servlet filter.
>> I'm not sure it can be in a Filter because of the interaction
>> with the saved-request features described above. If in a Filter,
>> the request would be saved before the Filter has a chance to see
>> it, then authentication would take place, etc.
>> I think this has to be in a Valve, and it has to happen before
>> the AuthenticatorValve sees the request. Do you see a way around
>> using a Valve? Assuming that such a Valve would be required, I
>> think we should provide one with Tomcat. I'd be happy to write
>> such a Valve.
> Can't comment because I don't know what exactly the "saved
> request" feature means, resp. how it works.

Well, the lb of course doesn't know if the session is valid. If it's
valid, the request *should* go to the requested node (sticky). If the
session is invalid, it should be re-balanced. Only the node itself can
determine the validity of the session.

Since the container's authenticator Valve intercepts requests to
protected resources in the above step #1 and takes-over, no Filter can
be used to intercede and redirect (to cause a re-balance to occur)
before step 2 occurs which defeats the whole process.

I'm working on a Filter that will work in our environment (we use
SecurityFilter, which, being a Filter, can be subverted by an
earlier-executing Filter). Once I have that proof-of concept, I'll
propose it as a new Valve available but not enabled by default.

- -chris
Version: GnuPG v1
Comment: GPGTools -
Comment: Using GnuPG with Thunderbird -


To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message