一:分布式 Session 不共享、不同步问题:
1)session 介绍:
a:由于HTTP协议是无状态的协议,一次浏览器和服务器的交互过程就是一次会话,对话完成后,这次会话就结束了,服务器端并不能记住这个人,下次再对话时,服务器端并不知道是上一次的这个人,所以服务端需要记录用户的状态时,就需要用某种机制来识别具体的用户,这个机制就是Session,服务端如何识别特定的客户?这个时候需要使用Cookie;每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session时,服务端会在HTTP协议中向客户端 Cookie 中记录一个Session ID,以后每次请求把这个会话ID发送到服务器,这样服务端就知道客户端是谁了;
2)session 会话管理:(Session 不同步 问题的出现)
a:在Web项目开发中,Session会话管理是一个很重要的部分,用于存储与记录用户的状态或相关的数据;通常情况下session交由容器(tomcat)来负责存储和管理,但是如果项目部署在多台tomcat中,则session管理存在很大的问题;1、多台tomcat之间无法共享session,比如用户在tomcat A服务器上已经登录了,但当负载均衡跳转到tomcat B时,由于tomcat B服务器并没有用户的登录信息,session就失效了,用户就退出了登录;2、一旦tomcat容器关闭或重启也会导致session会话失效;因此如果项目部署在多台tomcat中,就需要解决session共享的问题;
b:
c:
d:
二:分布式解决方案:
1):其他存储方式:
a:第一种是:session 复制:无需改动代码,配置容器即可,但是由于过于依赖容器,一旦容器升级或者更换意味着又得重新配置,而且容器负担大,适合小集群项目;
b:第二种是:session 信息存到 Cookie:不安全且占带宽。
c:第三种是:Hash一致性:使用Nginx负载均衡的ip_hash策略实现用户每次访问都绑定到同一台具体的后台tomcat服务器实现session总是存在;
d:第四种是:Spring session,这个方案既不依赖tomcat容器,又不需要改动代码,由Spring session框架为我们提供,可以说是目前非常完美的session共享解决方案;
2)后台统一存储:
a:图示:
b:不同服务:子域 Session 共享:
c:
d:
3)SpringSession 整合:(https://docs.spring.io/spring-session/docs/2.4.3/reference/html5/#samples:使用文档)
a:pom 文件:
<!--spring session-->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
b:配置文件:
spring.redis.host=114.215.173.88
spring.redis.port=6379
# session 存储类型 为 redis
spring.session.store-type=redis
#会话超时。如果未指定持续时间后缀,则使用秒
server.servlet.session.timeout=3000
#on_save#会话刷新模式。
#spring.session.redis.flush-mode=
# spring:session#用于存储会话的键的命名空间。
#spring.session.redis.namespace=gulimail:session:
c:开启 RedisSession:
d:存入Session:
@RequestMapping(value = "/testSession")
public String testSession(HttpSession session) {
UserLoginVo userLoginVo = new UserLoginVo();
userLoginVo.setNameOrPhone("李四");
userLoginVo.setPassword("123456");
session.setAttribute("loginUser", userLoginVo);
return "123";
}
e:从 session 取出:
@RequestMapping(value = "/testSession2")
public UserLoginVo testSession2(HttpSession session) {
Object loginUser = session.getAttribute("loginUser");
UserLoginVo userLoginVo = (UserLoginVo) loginUser;
return userLoginVo;
}
f:配置 CookieSerializer :(返回 浏览器的 Cookie 格式)
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("GULISESSION");
serializer.setCookiePath("/");
return serializer;
}
g:配置 RedisSerializer 序列化:(session 序列化到 redis 的格式)
@Bean
public RedisSerializer springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
4):
a:
b:
c:
d:
4)SpringSession 核心原理:
a:
b:
c:
d: