最近在研究Nginx+Tomcat实现负载均衡,实验成功后发现了一个问题:用户登录成功后,总是会自动退出系统。经过判断,发现在负载均衡的情况下,每次操作访问后台都有可能访问不同的Tomcat服务器,因此就会判断当前登录用户的session无效而导致退出系统。 解决这种问题的一个比较简单的方法就是在nginx的配置文件与负载均衡相关的配置处加入ip hash,这样每次就会只访问一台Tomcat服务器而不会退出系统。但是这样也有一个问题,就是如果访问的服务器挂了,就无法继续访问系统了。 咨询了一下同事,才知道可以用Tomcat+Nginx+Redis实现共享session,这样做既能达到负载均衡的目的,也能保持用户登录后session持久性,可谓一石二鸟。 采用Tomcat+Nginx+Redis实现分布式session共享大致分为3步: 1、 修改web系统配置; 2、 修改web系统中所有读取或操作session的地方; 3、 配置Nginx服务器。 下面分别来讲解一下这三步的操作: 1、 修改web系统配置 修改web系统配置也分3步: 1) 引入Redis的Maven依赖
<!-- Jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.2</version> </dependency> <!-- Spring Data Redis --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.5.2.RELEASE</version> </dependency> <!-- Spring Session --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.1.1.RELEASE</version> </dependency> <!-- Apache Commons Pool --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency>2) 配置Redis A) redis.properties
#redis主机地址 redis_hostName=127.0.0.1 #端口号 redis_port=6379 #密码 redis_password=123456 #连接超时时间 redis_timeout=20000B) spring-redis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <!-- session设置 --> <!-- maxInactiveIntervalInSeconds是设置session有效时间,以秒为单位, 但实际上无论怎么设,session真实有效时间还是会比我们设置的稍微长一些 --> <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"> <property name="maxInactiveIntervalInSeconds" value="3600" /> </bean> <!-- redis连接池 --> <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig" /> <!-- redis连接工厂 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="${redis_hostName}" /> <property name="port" value="${redis_port}" /> <property name="password" value="${redis_password}" /> <property name="timeout" value="${redis_timeout}" /> <property name="poolConfig" ref="poolConfig" /> </bean> </beans>3) 配置web.xml A) 在web.xml文件中要引入spring-redis.xml配置文件:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-redis.xml</param-value> </context-param>B) 同时,还要配置Filter
<!-- 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>通常情况下,如果有其他的过滤器,一般将Spring Session过滤器放到第一位。 2、 修改web系统中所有读取或操作session的地方; 1) 如登录过程中,需要将session放到内存中:
HttpSession session = request.getSession(); User user = userService.findByLogin(username, password); if(null != user){ //需要注意的是如果要往redis中存入对象,则需要将该对象序列化才能存入 session.setAttribute("loginUser", JSON.toJSONString(user)); }2) 在拦截器中获取session信息的代码: String userString = request.getSession().getAttribute(“loginUser”).toString(); User user = JSON.parseObject(userString, User.class); 3、 配置Nginx服务器: 至此,全部配置完成。对系统进行访问测试,用户登录后不会再发生因为session无效而退出系统的情况,系统已经能正常访问。