前面介绍了Spring Boot如何使用Redis缓存。接下来从项目实战出发,介绍使用Redis实现Session共享。
在分布式或微服务系统中,会出现这样一个问题:用户在服务器A上登录以后,假如后续的业务操作被负载均衡服务转发到服务器B上面,服务器B上没有这个用户的Session状态,就会强制让用户重新登录,导致业务无法顺利完成。因此,这就需要将Session进行共享,保证每个系统都能获取用户的Session状态。
一、分布式Session共享解决方案
目前主流的分布式Session共享主要有以下几种解决方案:
- 客户端存储,使用Cookie来完成,其缺点是不安全、不可靠。
- Session绑定,使用Nginx中的IP绑定策略,同一个IP指定访问同一个机器,其缺点是容易造成单点故障。如果某一台服务器宕机,那么该台服务器上的Session信息将会丢失。
- Session同步,使用tomcat内置的Session同步,其缺点是同步可能会产生延迟。
- Session共享,将Session存储在Redis等缓存中间件中。
以上解决方案各有优缺点,其中,比较流行的是使用Redis等缓存中间件的Session共享解决方案。将所有的Session会话信息存入Redis缓存中,然后Web应用从Redis中取出Session信息实现所有应用的Session共享。具体示意图如下图所示。
从上图可以看出,所有的服务都将Session的信息存储到Redis中,无论是对Session的注销、更新都会同步到Redis中,从而达到Session共享的目的。
二 、使用Redis实现Session共享
前面介绍了使用Redis实现Session共享的解决方案。下面通过示例演示使用Redis实现Session信息存储,并实现多系统的Session信息共享。
1.引入依赖
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!-- 引入 redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
上面的示例中,引入除了Redis组件外,还需要引入spring-session-data-redis依赖。通过此组件实现session信息的管理。
2.添加Session配置类
创建SessionConfig配置类,配置打开Session,示例代码如下:
@Configuration @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30) public class SessionConfig { }
上面的示例,配置Session的缓存时间。maxInactiveIntervalInSeconds:设置Session失效时间,使用Redis共享Session之后,原Spring Boot的server.session.timeout属性不再生效。
经过上面的配置后,Session调用就会自动去Redis上存取。另外,想要达到Session共享的目的,只需要在其他的系统上做同样的配置即可。
三、测试验证
首先,增加Session的测试方法。
@RequestMapping("/uid") String uid(HttpSession session) { UUID uid = (UUID) session.getAttribute("uid"); if (uid == null) { uid = UUID.randomUUID(); } session.setAttribute("uid", uid); return session.getId(); }
然后,启动项目,运行一个程序实例,启动端口号为8080,在浏览器中输入地址:“http://localhost:8080/uid”,页面返回会话的sessionId:
我们可以登录Redis客户端,查看session是否已经保存到Redis,输入“keys '*sessions*'”查看所有的Session信息:
从上面的输出可以看到,sessionId是7433a35d-a086-4b7d-bb64-37cf8b4e18f7,与页面返回的sessionId一致。说明Redis中缓存的SessionId和实际使用的Session一致,Session已经在Redis中进行有效的管理。
最后,我们模拟分布式系统,再启动一个程序实例,启动端口号为8081,在浏览器中输入“http://localhost:8081/uid”,页面返回会话的SessionId为:
从输出结果可以看到,程序实例1和程序实例2获取到的是同一个Session,这说明两个程序实现了Session共享。
最后
以上,我们就把Spring Boot使用Redis实现Session共享的问题介绍完了。Session共享是分布式和微服务的基础,通过Redis可以快速实现各服务、各系统之间的Session共享。
推荐阅读:
SpringBoot从入门到精通(二十八)JPA 的实体映射关系,一对一,一对多,多对多关系映射!
SpringBoot从入门到精通(二十七)JPA实现自定义查询,完全不需要写SQL!
SpringBoot从入门到精通(二十六)超级简单的数据持久化框架!Spring Data JPA 的使用!
SpringBoot从入门到精通(二十五)搞懂自定义系统配置
SpringBoot从入门到精通(二十四)3分钟搞定Spring Boot 多环境配置!