【Session共享(复制)】Session共享(复制)的4种实现方案

方案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


 

猜你喜欢

转载自blog.csdn.net/wjx_jasin/article/details/84300338