【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