Tomcat的Session共享(复制)的几种实现方案

1、为什么会提出这个问题?

使用Nginx+Tomcat进行负载均衡时,希望使用轮询方式进行负载。但是如果使用轮询方式的话,可能会访问不同的Tomcat,此时如果不进行Session共享,则相当于是一个新的Session。 就比如现有系统都是需要认证登录的系统,如果没有Session共享,则会导致用户退出登录。

2、方案1:使用Tomcat内置的Session复制方案

具体配置如下:




    
    
        
        
        
        
            
        
        
        
    
    
    
    
    




最终在Tomcat日志里可能会打印出如下日志信息:

29-Mar-2018 15:06:22.181 INFO [localhost-startStop-1] org.apache.catalina.ha.session.DeltaManager.getAllClusterSessions Manager [/ydzwV3], requesting session state from org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 233}:4010,{192, 168, 1, 233},4010, alive=572778, securePort=-1, UDP Port=-1, id={-56 73 0 62 -31 -122 65 -50 -108 49 -1 -12 -84 -32 -7 -77 }, payload={}, command={}, domain={}, ]. This operation will timeout if no session state has been received within 60 seconds.
29-Mar-2018 15:06:22.282 INFO [localhost-startStop-1] org.apache.catalina.ha.session.DeltaManager.waitForSendAllSessions Manager [/ydzwV3]; session state send at 3/29/18 3:06 PM received in 107 ms.

3、方案2:使用第三方(个人)基于Tomcat实现的Session管理

这里github上的tomcat-redis-session-manager来实现。
项目地址: https://github.com/jcoleman/tomcat-redis-session-manager
具体配置方法,在上述站点中有详细说明。在此不再赘述。
注意:这种方式还不支持Tomcat8。尽管有人基于上述代码进行了修改,但不能保证可用性。

4、方案3:使用Spring Session实现

Spring Session提供了多种方式来存储Session信息,包括redis、mongo、gemfire、hazelcast、jdbc等。这里用redis来举例说明,首先进行依赖添加,然后进行配置即可。

4、1 添加依赖(gradle)

compile "org.springframework.session:spring-session-data-redis:1.3.2.RELEASE"

注意:当引入上述依赖包时,还会引入如下依赖:

org.apache.commons:commons-pool2:2.4.2
org.springframework.data:spring-data-redis:1.7.10.RELEASE
org.springframework.session:spring-session:1.3.2.RELEASE
redis.clients:jedis:2.8.1

项目中原来使用了Redis作为Spring Cache的实现,当时使用的spring-data-redis是1.4.2.RELEASE版本,现在使用1.7.10.RELEASE版本后,需要把cacheManager这个Bean做如下调整:






4、2 进行Spring Session配置


 
???  这里怎么没有Redis连接配置  ??? 请看RedisHttpSessionConfiguration类中的如下代码:
// 这里会自动注入connectionFactory,而项目中已经注入了jedisConnectionFactory
@Bean
public RedisTemplate sessionRedisTemplate(
    RedisConnectionFactory connectionFactory) {
    RedisTemplate template = new RedisTemplate();
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    if (this.defaultRedisSerializer != null) {
        template.setDefaultSerializer(this.defaultRedisSerializer);
    }
    template.setConnectionFactory(connectionFactory);
    return template;
}

项目中注入的jedisConnectionFactory Bean如下:


所以,如果你项目中从来没有使用过Redis,也可以使用如下配置:




下面进行过滤器的配置:



    springSessionRepositoryFilter
    org.springframework.web.filter.DelegatingFilterProxy


    springSessionRepositoryFilter
    /*
至此,就配置完成啦!
在Redis中查看效果: 如果运行成功的话,可以在Redis中查看到key为spring:session:sessions的信息,如下所示:
Tomcat的Session共享(复制)的几种实现方案_第1张图片

Tomcat的Session共享(复制)的几种实现方案_第2张图片

5、方案对比

针对上述3中方案,以下仅是个人见解。
方案1:使用Tomcat内置的Session复制方案
SimpleTcpCluster
优点:内置
缺点:只适合Tomcat小集群,不适合大集群,因为session复制是all to all的方式
方案2:使用第三方(个人)基于Tomcat实现的Session管理
tomcat-session-manager
优点:已经实现对tomcat7的支持
缺点:第三方支持,支持力度不够,尤其是不能提供对Tomcat8的支持
方案3:使用Spring Session实现
基于redis存储实现
优点:不依赖于特定容器,官方支持
缺点:未发现

所以,我认为还是Spring Session来实现Session共享更加好用。

参考

参考1:N个Tomcat之间实现Session共享( https://blog.csdn.net/wlwlwlwl015/article/details/48160433
参考2:使用nginx搭建集群tomcat8,redis实现session共享,文件共享问题(https://blog.csdn.net/hua1586981/article/details/78132710)
参考3:使用tomcat-redis-session-manager实现session共享(https://blog.csdn.net/javandroid/article/details/52959105)
参考4:Nginx+Tomcat搭建集群,Spring Session+Redis实现Session共享(https://blog.csdn.net/u012702547/article/details/72991283?utm_source=tuicool&utm_medium=referral)
参考5:基于Spring XML配置的Spring Session Redis(https://docs.spring.io/spring-session/docs/current/reference/html5/guides/xml-redis.html
参考6:Spring Session Data Redis 配置中遇到的坑(https://blog.csdn.net/ankeway/article/details/72961346)
参考7:Clustering/Session Replication HOW-TO(https://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html)

你可能感兴趣的:(总结)