redisson-tomcat会话共享之session失效BUG排查
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redisson-tomcat会话共享之session失效BUG排查相关的知识,希望对你有一定的参考价值。
参考技术A 使用redisson-tomcat很简单,只需要两个步骤:在tomcat/conf/context.xml增加配置:
(rv表示redisson的版本号,tv表示tomcat的版本号)
参考 https://github.com/redisson/redisson/tree/master/redisson-tomcat
运维伙伴配置好负载均衡后(集群环境,一台一台发布,发布前剔除负载,发布后加入负载),我便开始测试。
一开始正常,但多次调试后,偶尔会出现session失效的问题,再次多次尝试后找到了session失效的触发条件:
第一次切换负载时,能正常访问,但第二次切换负载时,session会失效。
由于tomcat上层有slb做负载均衡、nginx做反向代理,首先得排查是不是它们引起的问题。
但这很难,于是我换了个思路,绕过上层直接访问tomcat,查看是否有问题。
排查流程:
tomcat返回Set-Cookie响应头,说明session已经失效,并重新创建了一个新的session。
所以,问题不是出在slb和nginx上。
考虑一番,打算直接从数据上查看是否有异样,重复上述步骤:
查看redis,一切正常:
查看redis,发现问题:
什么???
session的isValid变成false了,意味着session在第一次切负载的时候就已经失效了!
响应头依然有Set-Cookie,表示session的确失效了。
此时基本上确定问题是出在redisson-tomcat了。
在第一次getSession的时候,会调用sessionManager的createSession方法。
在切换负载的时候,会携带session id去访问另外一台tomcat,调用sessionManager的findSession方法:
乍眼一看,没有问题呀。
关键在于session.setId,调用了sessionManager的add(session)方法:
但是,到这一步也没问题。
问题在于,RedissonTomcat重写了sessionManager的add方法:
它调用了RedissonSession的自定义方法save
Redisson的save方法将所有字段同步到redis:
回过头看findSession,在还没有loadAttr的时候,就调用了setId方法,将一大堆还没有初始化好的值同步到了redis,导致session的isValid被置为false:
查看redisson的release记录,在最新版本已经修复了:
我们看一下,redisson是怎么修复的,仅仅是交换了setId和load(attrs)的顺序:
redisson 3.x版本最低要求jdk1.8,然而我们项目用的是jdk1.7。
于是我使用updateMode=AFTER_REQUEST模式暂时解决了这个问题。
AFTER_REQUEST原理是在tomcat容器的pipeline增加了一个Valve:
UpdateValve在请求结束后,同步所有字段到redis:
javaweb之HttpSession对象
1.session会话追踪原理 客户端第一次请求服务端,服务端会创建一个session对象并且存储下来,之后会将session的唯一标识sessionId设置到响应头中传给客户端 客户端之后请求就会在cookie中携带第一次请求后服务端传过来的sessionId,服务端能通过客户端传过来的sessi
以上是关于redisson-tomcat会话共享之session失效BUG排查的主要内容,如果未能解决你的问题,请参考以下文章
web存储机制(localStorage和sessionStorage)