session集群的解决方案:
1.扩展指定server
利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。缺点:耦合Tomcat/Jetty等Servlet容器,不能随意更换容器。
2.利用Filter
利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。spring-session就是通过这样的思路实现的。
Spring Boot中spring session支持方式:
JDBC、MongoDB、Redis、Hazelcast
由于redis现在市场使用较多,同时也是较为经典的一种是用方式,所以这里直接使用redis来实现简单的集群
具体实现,首先引入依赖,pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
然后配置文件中的配置
# spring session使用存储类型 #spring.session.store-type=redis # spring session刷新模式:默认on-save #spring.session.redis.flush-mode=on-save #spring.session.redis.namespace= # session超时时间,单位秒 #server.session.timeout=30 #redis #spring.redis.host=localhost #spring.redis.port=6379 #spring.redis.password=123456 #spring.redis.database=0 #spring.redis.pool.max-active=8 #spring.redis.pool.max-idle=8 #spring.redis.pool.max-wait=-1 #spring.redis.pool.min-idle=0 #spring.redis.timeout=0
配置自己需要的配置即可,spring.session.store-type=redis表示Session存储类型,这里选择的是redis,它有REDIS,MONGODB,JDBC,HAZELCAST,NONE;可供选择。
测试代码:
我们这里是开了两个不同端口的服务,验证两个不同服务之间打印的sessonID是否相同来测试是否实现了数据的共享,两个服务代码如下
package com.wangx.boot.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController @RequestMapping("/web") public class WebController { @RequestMapping("/index") @ResponseBody public String index(HttpSession session) { System.out.println(session.getId()); return "第一个应用:" + session.getId(); } }
package com.wangx.boot.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController @RequestMapping("/web") public class WebController { @RequestMapping("/index") @ResponseBody public String index(HttpSession session) { System.out.println(session.getId()); return "第二个应用:" + session.getId();
}
}
访问分别访问http://localhost:8080/web/index和http://localhost:8081/web/index,执行结果如下:
可以看到两个不同服务直接输出的sessionID都是一致的。两个不同服务直接共享同一个session,这样就实现了数据的同步和共享,它的实现原理就是将session保存到redis中,两个服务使用的时候都是在redis中取数据,从而共享了数据。