Springboot Session共享实现原理及代码实例
在传统的单服务架构中,一般来说,只有一个服务器,那么不存在Session
共享问题,但是在分布式/集群项目中,Session共享则是一个必须面对的问题,先看一个简单的架构图:
在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达Nginx上之后,被
Nginx转发到TomcatA上,然后在TomcatA上往session中保存了一份数据,下次又来一个请求,这个请求被转发到Tomcat
B上,此时再去Session中获取数据,发现没有之前的数据。对于这一类问题的解决,思路很简单,就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是Redis):
1实战
1.1创建工程
首先创建一个SpringBoot工程,引入Web、SpringSession以及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
注意:
这里我使用的SpringBoot版本是2.1.4,如果使用当前最新版SpringBoot2.1.5的话,除了上面这些依赖之外,需要额外添加SpringSecurity依赖(其他操作不受影响,仅仅只是多了一个依赖,当然也多了SpringSecurity的一些默认认证流程)。
1.2配置Redis
spring.redis.host=192.168.66.128
spring.redis.port=6379
spring.redis.password=123
spring.redis.database=0
1.3使用
配置完成后,就可以使用SpringSession了,其实就是使用普通的HttpSession,其他的Session同步到Redis等操作,框架已经自动帮你完成了:
@RestController publicclassHelloController{ @Value("${server.port}") Integerport; @GetMapping("/set") publicStringset(HttpSessionsession){ session.setAttribute("user","javaboy"); returnString.valueOf(port); } @GetMapping("/get") publicStringget(HttpSessionsession){ returnsession.getAttribute("user")+":"+port; } }
考虑到一会SpringBoot将以集群的方式启动,为了获取每一个请求到底是哪一个SpringBoot提供的服务,需要在每次请求时返回当前服务的端口号,因此这里我注入了server.port。
接下来,项目打包:
打包之后,启动项目的两个实例:
java-jarsessionshare-0.0.1-SNAPSHOT.jar--server.port=8080
java-jarsessionshare-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表示请求转发的地址,/表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中
- proxy_redirect表示设置当发生重定向请求时,nginx自动修正响应头数据(默认是Tomcat返回重定向,此时重定向的地址是Tomcat的地址,我们需要将之修改使之成为Nginx的地址)。
配置完成后,将本地的SpringBoot打包好的jar上传到Linux,然后在Linux上分别启动两个SpringBoot实例:
nohupjava-jarsessionshare-0.0.1-SNAPSHOT.jar--server.port=8080&nohupjava-jarsessionshare-0.0.1-SNAPSHOT.jar--server.port=8081&
其中
- nohup表示当终端关闭时,SpringBoot不要停止运行
- &表示让SpringBoot在后台启动
配置完成后,重启Nginx:
/usr/local/nginx/sbin/nginx-sreload
Nginx启动成功后,我们首先手动清除Redis上的数据,然后访问192.168.66.128/set表示向session中保存数据,这个请求首先会到达Nginx上,再由Nginx转发给某一个SpringBoot实例:
如上,表示端口为8081的SpringBoot处理了这个/set请求,再访问/get请求:
可以看到,/get请求是被端口为8080的服务所处理的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。