Springboot Session共享实现原理及代码实例

网友投稿 459 2022-11-27


Springboot Session共享实现原理及代码实例

在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session

共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:

在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被

Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请czOEwbtabp求,这个请求被转发到 Tomcat

B 上,此时再去 Session中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):

1 实战

1.1 创建工程

首先 创建一个 Spring Boot 工程,引入 Web、Spring Session 以及 Redis:

创建成功之后,pom.xml 文件如下:

org.springframework.boot

spring-boot-starter-data-redis

org.springframework.boot

spring-boot-starter-web

org.springframework.session

spring-session-data-redis

注意:

这里我使用的 Spring Boot 版本是 2.1.4 ,如果使用当前最新版 Spring Boot2.1.5的话,除了上面这些依赖之外,需要额外添加 Spring Security 依赖(其他操作不受影响,仅仅只是多了一个依赖,当然也多了 Spring Security 的一些默认认证流程)。

1.2 配置 Redis

spring.redis.host=192.168.66.128

spring.redis.port=6379

spring.redis.password=123

spring.redis.database=0

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) {

return session.getAttribute("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),编辑 nginx.conf 文件:

在这段配置中:

upstream 表示配置上游服务器

javaboy.org 表示服务器集群的名字,这个可以随意取名字

upstream 里边配置的是一个个的单独服务

weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上

location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转http://发到刚刚配置好的服务集群中

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 的服务所处理的。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Jpa多数据源工程配置过程解析
下一篇:Java Integer.valueOf()和Integer.parseInt()的区别说明
相关文章

 发表评论

暂时没有评论,来抢沙发吧~