分布式Session共享解决方案

1.session复制

分布式Session共享解决方案_第1张图片

2.浏览器本地存储

分布式Session共享解决方案_第2张图片

3.负载均很Hash-IP一致性

分布式Session共享解决方案_第3张图片

4.服务端同一存储

分布式Session共享解决方案_第4张图片
这里采用服务端同一存储的方式解决分布式Session共享问题

演示存在的问题

环境准备
1.创建三个服务器
分布式Session共享解决方案_第5张图片
ac为认证服务器,oth1、oth2分辨扮演其他业务服
2.设置本地域名

C:\Windows\System32\drivers\etc

分布式Session共享解决方案_第6张图片
这里设置域名也是模拟线上环境,因为不同域名存在session跨域问题,
3.导入依赖-这里的依赖

4.编写伪代码
ac服务器

login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
    <ul>
        <li class="top_1">
            <input type="text" name="username" placeholder=" 邮箱/用户名/已验证手机" class="user" />
        </li>
        <li>
            <input type="password" name="password" placeholder=" 密码" class="password" />
        </li>
        <li class="ent"><button type="submit" class="btn2"><a>&nbsp; &nbsp;</a></button></li>
    </ul>
</form>
</body>
</html>



ok.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>ac-ok</title>
</head>
<body>
登录成功!!!
欢迎[[${session.data}]]
</body>
</html>

controller
@PostMapping("/login")
public String list(UserEntity userEntity, HttpSession session){
	log.debug("ac");
    UserEntity userRes=userService.query(userEntity);
    session.setAttribute("data","ac");
    log.debug(userRes.toString());
    return "ok";
}
//这里还缺一个login.html的视图解析器
//自己创建一个/映射一下

oth1服务器

oth1.html
 <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>oth1-ok</title>
</head>
<body>
登录成功!!!
欢迎[[${session.data}]]
</body>
</html>

 controller
 @GetMapping("/Oth1")
    public String list( HttpSession session){
        log.debug("Oth1");
        return "oth1";
    }

oth2服务器

oth2.html
 <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>oth2-ok</title>
</head>
<body>
登录成功!!!
欢迎[[${session.data}]]
</body>
</html>

 controller
 @GetMapping("/Oth2")
    public String list( HttpSession session){
        log.debug("Oth2");
        return "oth2";
    }

5.访问测试
这里采用火狐浏览器,其实我个人比较喜欢谷歌浏览器,但是公司有项目开发,还有一些个人账号信息存储在谷歌浏览器里面,不想被清空数据从新登陆,所以就用火狐这个备胎了!!!

AC登陆
分布式Session共享解决方案_第7张图片
登陆成功
分布式Session共享解决方案_第8张图片
登陆ac服务器成功,取的ac服务器的session

访问Oth1界面
分布式Session共享解决方案_第9张图片
这里虽然存在session但是在代码里面没有给Oth1服务器的session中存值

访问Oth2界面
分布式Session共享解决方案_第10张图片
这个Oth2服务器索性连session都没有

问题分析
不同服务器间session不共享,不同域名下session数据不共享,controller默认不携带session数据!
这里不同服务器session数据不共享还好理解,但是不同域名下session数据不共享就有点懵逼,演示一下,把session的作用域扩大到test.com范围在尝试,服务器不做变动!
分布式Session共享解决方案_第11张图片
在浏览器上将ac的session的域范围扩大为.test.com然后在Oth1、Oth2界面刷新,查看到Oth1、Oth2的cookie中确实多出的test.com的session,那么Oth1、Oth2的cookie中都存在session那么就能理所应当像ac一样取出session中的值,渲染为111,这里其实并不是,虽然session的域范围Oth1、Oth2确实是有了,但是在html界面渲染时Oth1、Oth2服务器的session里面并没有存在这样的值,所以Oth1、Oth2的html界面在服务器渲染后的session的值也是没有的!

解决session数据共享

session数据共享问题,spring为我们提供了非常成熟的技术方案!SpringSession,使用redis做session的统一存储,让各服务器都能共享redis中的session数据

1.导入MVN依赖

 		<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>

2.开启SpringSession
分布式Session共享解决方案_第12张图片
3.配置YML
分布式Session共享解决方案_第13张图片

  session:
    store-type: redis


servlet:
    session:
      timeout: 30m

4.测试访问
查看登录后的AC服务器session
分布式Session共享解决方案_第14张图片
查看redis分布式Session共享解决方案_第15张图片
这里现在分配的作用域是子域名的,现在还不能跨域共享数据

5.手动修改ac的session的作用域
分布式Session共享解决方案_第16张图片
6.刷新Oth2界面,服务器不做任何变动
分布式Session共享解决方案_第17张图片
这里Oth2服务器的代码没动,浏览器刷新Oth2的时候会检测当前域名,上个步骤中将AC的二级ac.test.com的作用域设置为了test.com所以Oth2.test.com也会获得父域名下的session数据,这里我们是手动修改的session的作用域,那么我们在后端用代码实现!

1.默认令牌为session=xxxxxxxxxxxxxx
2.作用域为当前服务器访问域名

补充:这里由于是演示代码,session中存储的是简单字符串,如果在多系统环境中,不同语言的数据类型不一样,会导致数据无法解析,那么可以是采用JSON来解决数据兼容性问题

解决问题

添加SpringSession配置类

@Configuration
public class SessionConfig {
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("test.com");
        cookieSerializer.setCookieName("TESTSESSION");
        return cookieSerializer;
    }

    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

重启服务器
访问ac
分布式Session共享解决方案_第18张图片
这里的session的作用域为test.com
查看Oth2
分布式Session共享解决方案_第19张图片
这里访问直接能够拿到父域test.com的值

Redis中session的JSON序列化
分布式Session共享解决方案_第20张图片
分布式Session的解决方案就演示完成了,后面还会结合单点登录,整合SpringSecurity来做一个整体的案例

你可能感兴趣的:(JAVA,SpringBoot)