在传统的单服务架构中,一般来说,只有一个服务器,那么不存在Session共享问题,但是在分布式/集群项目中,Session共享则是一个必须面对的问题,先看一个简单的架构图:
在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达Ngix,上之后,被Nginx转发到Tomcat A上,然后在Tomcat A上往session中保存了一份数据,下次又来一个请求,这个请求被转发到Tomcat B上,此时再去Session中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是Redis):
当所有Tomcat需要往Session中写数据时,都往Redis中写,当所有Tomcat需要读数据时,都从 Redis中读。这样,不同的服务就可以使用相同的Session数据了。 这样的方案,可以由开发者手动实现,即手动往Redis中存储数据,手动从Redis中读取数据,相当于使用一些Redis客户端工具来实现这样的功能,毫无疑问,手动实现工作量还是蛮大的。 一个简化的方案就是使用Spring Session来实现这一功能,Spring Session就是使用Spring中的代理过滤器,将所有的Session操作拦截下来,自动的将数据同步到Redis中,或者自动的从Redis中读取数据。对于开发者来说,所有关于Session同步的操作都是透明的,开发者使用Spring Session,一旦配置完成后,具体的用法就像使用一个普通的Session一样。
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
?配置链接redis
spring.redis.port=6379
spring.redis.host=192.168.70.129
spring.redis.password=111111
?测试
@RestController
public class helloController {
@Value("${server.port}")
Integer port;
@RequestMapping("/set")
public String set(HttpSession httpsession){
httpsession.setAttribute("name","xiaoxiao");
return port.toString();
}
@RequestMapping("/get")
public String get(HttpSession httpsession){
String name=(String) httpsession.getAttribute("name");
return name+":"+port;
}
}
?打包,分别用8080端口和8088端口运行jar包
java -jar httpsession-0.0.1-SNAPSHOT.jar --server.port=8080
java -jar httpsession-0.0.1-SNAPSHOT.jar --server.port=8088
?
?
?
?
?
|