SpringbootSession共享实现原理及代码实例
在传统的单服务架构中,⼀般来说,只有⼀个服务器,那么不存在 Session
共享问题,但是在分布式/集项⽬中,Session 共享则是⼀个必须⾯对的问题,先看⼀个简单的架构图:
在这样的架构中,会出现⼀些单服务中不存在的问题,例如客户端发起⼀个请求,这个请求到达 Nginx 上之后,被
Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了⼀份数据,下次⼜来⼀个请求,这个请求被转发到Tomcat
B 上,此时再去 Session中获取数据,发现没有之前的数据。对于这⼀类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到⼀个公共的地⽅(主流⽅案就是 Redis):
1 实战
1.1 创建⼯程
⾸先创建⼀个 Spring Boot ⼯程,引⼊ Web、Spring Session 以及 Redis:
创建成功之后,l ⽂件如下:
<dependencies>
<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>springboot原理图解
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
注意:
这⾥我使⽤的 Spring Boot 版本是 2.1.4 ,如果使⽤当前最新版 Spring Boot2.1.5的话,除了上⾯这些依赖之外,需要额外添加 Spring Security 依赖(其他操作不受影响,仅仅只是多了⼀个依赖,当然也多了 Spring Security 的⼀些默认认证流程)。
1.2 配置 Redis
1.3 使⽤
配置完成后,就可以使⽤ Spring Session 了,其实就是使⽤普通的 HttpSession ,其他的 Session 同步到 Redis 等操作,框架已经⾃动帮你完成了:
@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/set")
public String set(HttpSession session) {
session.setAttribute("user", "javaboy");
return String.valueOf(port);
}
@GetMapping("/get")
public String get(HttpSession session) {
Attribute("user") + ":" + port;
}
}
考虑到⼀会 Spring Boot 将以集的⽅式启动,为了获取每⼀个请求到底是哪⼀个 Spring Boot 提供的服务,需要在每次请求时返回当前服务的端⼝号,因此这⾥我注⼊了 server.port 。
接下来,项⽬打包:
打包之后,启动项⽬的两个实例:
java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080
java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8081
然后先访问 localhost:8080/set 向 8080 这个服务的 Session 中保存⼀个变量,访问完成后,数据就已经⾃动同步到 Redis 中了:
然后,再调⽤ localhost:8081/get 接⼝,就可以获取到 8080 服务的 session 中的数据:
此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了,但是每次访问都是我⾃⼰⼿动切换服务实例,因此,接下来我们来引⼊ Nginx ,实现服务实例⾃动切换。
1.4 引⼊ Nginx
很简单,进⼊ Nginx 的安装⽬录的 conf ⽬录下(默认是在 /usr/local/nginx/conf),编辑 f ⽂件:
在这段配置中:
upstream 表⽰配置上游服务器
< 表⽰服务器集的名字,这个可以随意取名字
upstream ⾥边配置的是⼀个个的单独服务
weight 表⽰服务的权重,意味者将有多少⽐例的请求从 Nginx 上转发到该服务上
location 中的 proxy_pass 表⽰请求转发的地址,/ 表⽰拦截到所有的请求,转发转发到刚刚配置好的服务集中
proxy_redirect 表⽰设置当发⽣重定向请求时,nginx ⾃动修正响应头数据(默认是 Tomcat 返回重定向,此时重定向的地址是 Tomcat 的地址,我们需要将之修改使之成为 Nginx 的地址)。
配置完成后,将本地的 Spring Boot 打包好的 jar 上传到 Linux ,然后在 Linux 上分别启动两个 Spring Boot 实例:nohup java -jar sessionshare-0.0.1-SNAPSHOT.jar --server.port=8080 & nohup java -jar sessionshare-0.0.1-
SNAPSHOT.jar --server.port=8081 &
其中
nohup 表⽰当终端关闭时,Spring Boot 不要停⽌运⾏
& 表⽰让 Spring Boot 在后台启动
配置完成后,重启 Nginx:
/usr/local/nginx/sbin/nginx -s reload
Nginx 启动成功后,我们⾸先⼿动清除 Redis 上的数据,然后访问 192.168.66.128/set 表⽰向 session 中保存数据,这个请求⾸先会到达 Nginx 上,再由 Nginx 转发给某⼀个 Spring Boot 实例:
如上,表⽰端⼝为 8081 的 Spring Boot 处理了这个 /set 请求,再访问 /get 请求:
可以看到,/get 请求是被端⼝为 8080 的服务所处理的。
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。