场景:在项目集群部署的时候遇到的一个坑,Nginx+Tomcat集群后发现,登陆总是登陆不上,亦或者是登陆上了一次,下一次请求又回到了登陆页,造成根本无法正常操作。在查询原因后发现了问题所在。 第一次请求被nginx分配到了Tomcat1,这时Session存在了Tomcat1,第二次请求却被分配到了Tomcat2。Tomcat2并没有已登录的Session,因此跳回了登录页,如此循环。。因此就需要在多台server之间共享session。
session共享的方法有很多,有tomcat自带的session共享,ehcache的集群同步,memcached,12306用的gemfire(这个以后有机会在研究吧哈哈)等等,这里我用redis的两种形式来实现session共享。
第一种:Tomcat可以依赖redis的lib包来实现共享, 这是比较简单的。
Step1:将三个redis相关jar包放入tomcat7的lib中。
三个jar包由
Tomcat-redis-session-manager打包生成
注意:jar包不通用。tomcat8需要重新打包,代码有些变化。
Step2
:修改tomcat配置文件context.xml
Context标签中新增如下配置,主机地址、端口以及密码等自行配置
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="192.168.1.137"
port="6379"
password="123456"
database="0"
maxInactiveInterval="60"/>
Step3
:启动tomcat、开启集群就行了。。
这是比较简单的session共享,但是每个tomcat都需要加入lib以及修改配置文件。这样集群的时候比较繁琐、那么继续往下看。
第二种:利用spring-session-data-redis
Step1
:pom加入依赖:
<!-- spring session redis begin -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<!-- spring session redis end -->
Step2:修改spring-mvc.xml配置,主机地址、端口以及密码自行配置
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="30" />
<property name="maxIdle" value="10" />
<property name="minIdle" value="1" />
<property name="maxWaitMillis" value="30000" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="false" />
</bean>
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="600" />
</bean>
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
destroy-method="destroy">
<property name="hostName" value="192.168.1.137" />
<property name="port" value="6379" />
<property name="password" value="123456" />
<property name="timeout" value="3000" />
<property name="usePool" value="true" />
<property name="poolConfig" ref="jedisPoolConfig" />
</bean>
项目中还有用到redis可加入:
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
Step3:web.xml加入拦截器
<!-- Spring Session过滤器 begin -->
<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>
<!-- Spring Session过滤器 end -->
至此配置完成。通过spring-session存储到redis中,项目部署也方便很多。
本文中很多也是借鉴了网上前辈的经验,再结合自身项目实际需求舍取,大家也可以根据自身项目的场景应用。
请多指教,欢迎留言。