1. 程式人生 > >【Session共享(複製)】Session共享(複製)的4種實現方案

【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