java 编码 session共享_Springboot Session共享实现原理及代码实例

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

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

db48911ddfddfd93031d8dcce702657f.png

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

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

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

344ef680184ef605e6fe47f424933f95.png

1 实战

1.1 创建工程

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

e8dfb100ccc162a9fa3eec1172a7bb3b.png

创建成功之后,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 。

接下来 ,项目打包:

837e955b0018d6d930601ccf675b9bd8.png

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

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

b744a4fea7cda57d8c60b0284795efa9.png

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

9547c7e36222d71c721cbb1c72b77a37.png

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

1.4 引入 Nginx

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

c2c2793cdd2bb14b69e5c8416d3881c0.png

在这段配置中:

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

9eb95c86a7fddb57254783f66066448c.png

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

17d20b82bca57ae7a890f1f0c452fcb2.png

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值