问题
I have implemented Spring Session with Redis
in my legacy Spring MVC application. I also used the DefaultCookieSerializer
to set the jvmRoute
, because I need some server affinity for Talend jobs to be able to run.
When I run the front end and inspect the page in Chrome, I see the jvmRoute
appended to the session. If I edit this from "node1" to "node2", the session is preserved. If I redeploy the server and make requests during that deployment, I get redirected to another node in the cluster, which means that Spring Sessions is working perfect.
However, I cannot get server affinity because when I debug a HttpServletRequest
as it comes into my Spring app, the HttpServletRequest.getSession().getId()
doesn't have the jvmRoute
in it (although the hex number matches what I see in Chrome), and this is what I pass to the Talend job.
If I revert back to Tomcat session and set the jvmRoute
in the Engine component of server.xml
, I see the jvmRoute
appended to the session id in both Chrome and when debugging the code.
What exactly does the DefaultCookieSerializer
do? I thought it edits the cookie as it is being created, and that is how the cookie is to be stored in Redis
. So any use of this cookie subsequent to being created should have the jmvRoute
attached if you set it up that way.
回答1:
What exactly does the DefaultCookieSerializer do? I thought it edits the cookie as it is being created, and that is how the cookie is to be stored in Redis. So any use of this cookie subsequent to being created should have the jmvRoute attached if you set it up that way.
First, it's important to realize the cookie itself isn't stored in session store (i.e. Redis in your case). What's stored is the representation of session itself, along with its attributes.
Besides session storage, other important aspect of session management is the correlation of user's HTTP request with the stored session. With Spring Session's Servlet API support this is the responsibility of HttpSessionIdResolver
, and by default Spring Session uses cookie based implementation i.e. CookieHttpSessionIdResolver
. There's also an HTTP header based implementation in HeaderHttpSessionIdResolver
. I'm stating this because it's important to realize that session storage are distinct concerns that operate on different levels.
Now, regarding the CookieHttpSessionIdResolver
, it delegates cookie writing and reading concerns to CookieSerializer
(with DefaultCookieSerializer
being the... well, default implementation). According to its configuration, DefaultCookieSerializer
will respect a number of options when writing and reading session cookies i.e. cookie name, whether to Base64 encode cookie value, whether to use httpOnly
cookie directive etc.
However, I cannot get server affinity because when I debug a HttpServletRequest as it comes into my Spring app, the HttpServletRequest.getSession().getId() doesn't have the jvmRoute in it (although the hex number matches what I see in Chrome), and this is what I pass to the Talend job.
This is the part that I don't understand - if you're able to resolve HttpSession
from the current HttpServletRequest
then you know what jvmRoute
it's bound to right? It's the jvmRoute
of the current JVM, otherwise session wouldn't be resolved HttpServletRequest
in handled by this JVM.
What's different between the Spring Session and Tomcat's session management, is that with Tomcat the jvmRoute
is session id generation related concern while with Spring Session the jvmRoute
is used in the context of session cookie serialization.
来源:https://stackoverflow.com/questions/51868693/springsession-defaultcookieserializer-setjvmroute-works-but-httpservletrequest