SpringBoot开发案例之分布式集群共享Session
前言
在分布式系统中,为了提升系统性能,通常会对单体项目进行拆分,分解成多个基于功能的微服务,如果有条件,可能还会对单个微服务进行水平扩展,保证服务高可用。
那么问题来了,如果使用传统管理 Session 的方式,我们会遇到什么样的问题?
案例
这里拿下单举例,用户小明在天猫上相中了一个的娃娃,觉得不错,果断购买,选尺寸,挑身高,然后确认选择,赶紧提交订单,然后就跳转到了登录页面!小明表示很郁闷,大写的问号???
-
小明进入娃娃页面,此时请求通过代理服务发送到业务系统一。
-
小明选尺寸,挑身高,此操作并没有对后端服务发送请求。
-
小明提交订单,此时请求通过代理服务发送到业务系统二,然鹅,二系统此时并没有查询到小明的登录信息,就被无情的跳转到登录页了。
方案
HttpSession 默认使用内存来管理 Session,通常服务端把用户信息存储到各自的 Jvm 内存中。所以小明下单的时候找不到登录信息,那么我么何不把用户信息集中存储!?
为了测试效果,这里我们搭建一个演示案例,项目涉及 SpringBoot、spring-session、redis、nginx 等相关组件。
pom.xml引入依赖:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
|
< dependency > < groupId > org.springframework.session < / groupId > < artifactId > spring - session - data - redis < / artifactId > < / dependency > < dependency > < groupId > org.springframework.boot < / groupId > < artifactId > spring - boot - starter - data - redis < / artifactId > < / dependency > |
配置 redis 参数,软件自行安装:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
|
## redis #session存储类型 spring.session.store - type = redis spring.redis.database = 0 spring.redis.host = 127.0 . 0.1 spring.redis.port = 6379 spring.redis. password = 123456 spring.redis.pool.max - active = 8 spring.redis.pool.max - wait = -1 spring.redis.pool.max - idle = 8 spring.redis.pool.min - idle = 0 spring.redis.timeout = 3000 |
简单的用户登录实现,省略部分代码:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@RequestMapping ( value = "login" , method = RequestMethod.POST ) public Result login ( String username , String password , HttpServletRequest request , HttpServletResponse response ) throws Exception { SysUser user = userService.getUser ( username ) ; if ( user = = null ) { return Result. error ( "用户不存在" ) ; } else { if ( user.getPassword ( ) . equals ( password ) ) { request.getSession ( ) .setAttribute ( "user" , user ) ; return Result.ok ( ) ; } else { return Result. error ( "密码错误" ) ; } } } |
配置代理实现,基于 Nginx:
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
server { listen 80 ; server_name blog. 52 itstyle.vip; location / { proxy_pass [ url = http : / / 192.1 68.1 . 2 : 8080 ;]http : / / 192.1 68.1 . 2 : 8080 ;[ / url ] } location / cart { proxy_pass [ url = http : / / 192.1 68.1 . 3 : 8080 ]http : / / 192.1 68.1 . 3 : 8080 [ / url ]$request_uri; } location / order { proxy_pass [ url = http : / / 192.1 68.1 . 4 : 8080 ]http : / / 192.1 68.1 . 4 : 8080 [ / url ]$request_uri; } } |
配置成功后登录系统,在 redis 中查询用户信息:
[AppleScript] 纯文本查看 复制代码
1
2
3
4
|
127.0 . 0.1 : 6379 > keys * 1 ) "spring:session:expirations:1562577660000" 2 ) "spring:session:sessions:1076c2bd-95b1-4f23-abd4-ab3780e32f6f" 3 ) "spring:session:sessions:expires:1076c2bd-95b1-4f23-abd4-ab3780e32f6f" |