Tomcat分布式Session共享

2015-07-20 veryyoung 更多博文 » 博客 » GitHub »

原文链接 http://veryyoung.me/blog/2015/07/20/tomcat-redis-session-manager.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


tomcat-redis-session-manager

用tomcat默认的方式来管理session是很有问题的,比如项目重启tomcat,用户会话就会丢失,这样用户体验非常糟糕。应用只要稍微上点规模或者需要多机负载,这是必须做的工作了。

web server自带解决方案有2:

tomcat有自带的session共享方式cluster,多个tomcat实时复制session。缺点是服务器之间会频繁的进行数据同步,如果在不同机器上网络开销会非常大,而且数据同步会有延迟的,这可能导致数据不一致,还有缺点就是session在每台机器都保有一份,太浪费资源了! ngnix有基于ip hash转发的策略,用这个来保证每个IP每次访问到的都是同一个tomcat实例。缺点很明显,在多用共享同一IP的情况下一点负载均衡的作用都木有了。

很自然能想到的方法就是把tomcat的session交给memcached或者redis去集中管理。这样不管tomcat如何增加减少或者重启,和session都没关系。

本来打算自己实现一套,上git随便搜了下,发现早就有现成的解决方案了。 https://github.com/jcoleman/tomcat-redis-session-manager

使用方法很简单:

git clone git@github.com:jcoleman/tomcat-redis-session-manager.git gradle build -x test copyJars 最好build之前注释掉build.gradle里面的maven私仓 复制 tomcat-redis-session-manager-{version}.jar commons-pool2-2.2.jar jedis-2.5.2.jar 到每个tomcat的lib目录下 修改tomcat/conf/context.xml 加入<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager" host="localhost" port="6379" database="0" maxInactiveInterval="60" /> 启动两个tomcat(如果是同一台机器需要指定不同的端口) 在nginx conf增加upstream,指定这两天tomcat的访问url nginx -s reload 测试。访问任意一台tomcat,然后redis-cli 可以看到session已写入redis,再访问另外一台,session不变

原理 tomcat提供了org.apache.catalina.session.ManagerBase基类来扩展session管理。 在对应生成session之后管理session的地方存储到jedis,然后getSession也从jedis取。