方案1:使用Tomcat内置的Session复制方案
具体配置如下:
<!-- 第1步:修改server.xml,在Host节点下添加如下Cluster节点 -->
<!-- 用于Session复制 -->
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true" />
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4"
port="45564" frequency="500" dropTime="3000" />
<!-- 这里如果启动出现异常,则可以尝试把address中的"auto"改为"localhost" -->
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000"
autoBind="100" selectorTimeout="5000" maxThreads="6" />
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender" />
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor" />
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter="" />
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve" />
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer" tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/" watchDir="/tmp/war-listen/" watchEnabled="false" />
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener" />
</Cluster>
<!-- 用于Session复制 -->
方案2:使用第三方(个人)基于Tomcat实现的Session管理(tomcat 8以下版本)
这里github上的tomcat-redis-session-manager来实现。
项目地址:https://github.com/jcoleman/tomcat-redis-session-manager
具体配置方法,在上述站点中有详细说明。在此不再赘述。
注意:这种方式还不支持Tomcat8。尽管有人基于上述代码进行了修改,但不能保证可用性。
方案3:使用Spring Session实现(Redis实现Session共享)
3.1 ssm方式
Jar包准备:
commons-pool2-2.4.2.jar
jedis-2.9.0.jar
spring-data-redis-1.7.3.RELEASE.jar
spring-session-1.2.2.RELEASE.jar
spring(本次使用的为4.2.5版本)
Spring整合Redis
第一种方式:----------------------------------------------------------已测试-----------------------------------------------------------------------
<!-- redis连接配置,依次为主机ip,端口,是否使用池,(usePool=true时)redis的池配置 -->
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="600"/>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="600" />
<property name="maxIdle" value="300" />
</bean>
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
<property name="hostName" value="127.0.0.1"/>
<property name="port" value="6379"/>
<property name="password" value="" />
<property name="timeout" value="3000"/>
<property name="usePool" value="true"/>
<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>
第二种方式:--------------------------------------------------未测试-----------------------------------------------------------------------
<!--
第1步:在Spring配置文件中添加如下bean
以后在web.xml中配置session超时时间就无效了,如果需要指定session超时时间,则使用maxInactiveIntervalInSeconds来指定,默认是1800s=30min
-->
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"
p:maxInactiveIntervalInSeconds="1800"/>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.hostname}"
p:port="${redis.port}"
p:database="${redis.database}"
p:poolConfig-ref="redispoolconfig"
p:use-pool="${redis.usepool}">
</bean>
如果你项目中从来没有使用过Redis,也可以使用如下配置:
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
<!--
Jdeis连接工厂Bean
注意:这种方式没有使用连接池,生产环境下务必需要使用连接池
-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="192.168.1.233"
p:port="6379"
p:database="15"
p:usePool="false">
</bean>
web.xml增加filter
<!--redis session-->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.2 spring-boot方式
<!-- springboot - Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--spring session 与redis应用基本环境配置,需要开启redis后才可以使用,不然启动Spring boot会报错 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
application.properties 特别注意此处需要spring.session.store-type
######################## Redis ###################################
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
# 连接池最大连接数
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
spring.session.store-type=redis
config @EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1800)
@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1800)
public class SessionApplication {
}
上面的例子中,使用的是Redis来存储应用的session,当然spring session还支持以下几种方式:
EnableGemFireHttpSession
EnableMongoHttpSession
EnableJdbcHttpSession
方案4:nginx ip_hash技术
当某个ip下的客户端请求指定(固定,因为根据IP地址计算出一个hash值,根据hash值来判断分配给那台服务器,从而每次该ip请求都分配到指定的服务器)的服务器,这样就可以保证有状态请求的状态的完整性,不至于出现状态丢失的情况。
upstream nginx.xx.com {
server 192.168.1.2:80;
server 192.168.1.3:80;
ip_hash;
}
方案对比
方案1:使用Tomcat内置的Session复制方案SimpleTcpCluster | 优点:内置,便于服务器水平扩展,对应用无入侵 缺点:只适合Tomcat小集群,不适合大集群,因为session复制是all to all的方式,性能低,内存消耗 |
方案2:使用第三方(个人)基于Tomcat实现的Session管理 tomcat-session-manager | 优点:已经实现对tomcat7的支持,对应用无入侵 缺点:第三方支持,支持力度不够,尤其是不能提供对Tomcat8的支持 |
方案3:使用Spring Session实现 基于redis存储实现 | 优点:不依赖于特定容器,官方支持,适合大集群,能适应各种负载均衡策略,扩展能力强 缺点:对应用有入侵,需增加相关配置。 |
方案4:nginx ip_hash技术 | 优点:配置简单,无代码修改 缺点:服务器重启丢失问题,单点负载过高,单点故障问题 |
参考
参考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)
参考8:https://blog.csdn.net/u012383839/article/details/79756368