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

作者:柒丶月 时间:2022-12-16 03:29:52 

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

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

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

在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被
Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat
B 上,此时再去 Session中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):

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

1 实战

1.1 创建工程

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

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

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


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

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 。

接下来 ,项目打包:

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

打包之后,启动项目的两个实例:

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 中 了 :

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

然后,再调用 localhost:8081/get 接口,就可以获取到 8080 服务的 session 中的数据:

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

此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了,但是每次访问都是我自己手动切换服务实例,因此,接下来我们来引入 Nginx ,实现服务实例自动切换。

1.4 引入 Nginx

很简单,进入 Nginx 的安装目录的 conf 目录下(默认是在 /usr/local/nginx/conf),编辑 nginx.conf 文件:

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

在这段配置中:

  • upstream 表示配置上游服务器

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

  • 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 实例:

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

如上,表示端口为 8081 的 Spring Boot 处理了这个 /set 请求,再访问 /get 请求:

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

可以看到,/get 请求是被端口为 8080 的服务所处理的。

来源:https://www.cnblogs.com/qiuwenli/p/13442916.html

标签:Spring,boot,Session,共享
0
投稿

猜你喜欢

  • Spring Bean生命周期之BeanDefinition的合并过程详解

    2023-11-29 02:50:35
  • Java面向对象实现汽车租赁系统

    2023-05-20 07:03:06
  • Java多线程之同步锁-lock详解

    2023-12-16 14:40:08
  • 关于SpringGateway调用服务 接受不到参数问题

    2023-08-31 13:05:00
  • 老生常谈Java 网络编程 —— Socket 详解

    2023-07-12 16:32:54
  • Zookeeper事务日志预分配空间解读

    2022-03-16 22:36:49
  • spring boot集成smart-doc自动生成接口文档详解

    2023-11-28 23:08:02
  • 关于springboot配置文件密文解密方式

    2023-11-09 04:21:24
  • java实现航空用户管理系统

    2023-11-24 02:42:37
  • java的main方法中调用spring的service方式

    2023-03-29 00:12:16
  • opencv利用鼠标滑动画出多彩的形状

    2023-11-03 05:20:57
  • Java开发Oracle数据库连接JDBC Thin Driver 的三种方法

    2022-05-08 09:40:50
  • Netty实现简易版的RPC框架过程详解

    2023-05-23 23:19:58
  • Spring bean的实例化和IOC依赖注入详解

    2023-11-23 23:57:15
  • ios百度地图的使用(普通定位、反地理编码)

    2023-07-03 15:26:17
  • JDBC自定义连接池过程详解

    2023-11-17 13:27:55
  • Java二分查找算法与数组处理的应用实例

    2022-07-11 01:26:57
  • java 避免出现NullPointerException(空指针)的方法总结

    2022-08-31 04:15:51
  • Java面试题冲刺第二十五天--并发编程3

    2023-09-11 04:40:10
  • android异步消息机制 源码层面彻底解析(1)

    2023-10-02 07:08:52
  • asp之家 软件编程 m.aspxhome.com