Loading

分布式session的解决方法

一、背景

上篇博客,使用微博社交登录谷粒商城后,将用户信息保存在session中,此时进入到谷粒商城的任何页面都需要能够取到用户信息,

谷粒商城首页(gulimall.com/index.html),  首页搜索商品后搜索到的商品列表(search.gulimall.com/index.html)

image




二、session的原理

0



三、分布式服务下session存在的问题

1、分布式服务下的session共享问题

微服务架构下,每个服务存在 多个示例,因为session的默认实现是内存中的map,所以不同实例的session是不能共享的,

若第一次请求路由到会员1服务,并在session中存放了东西,第二次请求路由到会员2服务,此时,会员2服务是不能取到session中的内筒的

0

分布式session解决方案

①、session复制

0


②、客户端cookie存储原本存在session中的内筒

0


③、hash一致性

0


④、统一存储

一般情况下使用该方法解决分布式服务中,多个实例 的session共享问题

0


2、不同服务,子域session共享

例如:上述阐述的背景中,你通过auth服务进行登录,并使用session将用户信息保存在其中,此时auth服务会在浏览器中保存一个

cookie,cookie中携带jsessionid,但是这个cookie只会在浏览器访问auth.gulimall.com中携带,访问其他域名的服务(例如gulimall.com,search.gulimall.com)

则不会携带该cookie,没有jessionid,则自然不能拿到该用户存在session中的内容,不能共享

0


四、使用SpringSession来解决上述提到的两个问题

使用 SpringSession 解决分布式服务下session的共享问题 + 子域间session共享问题

①、引入SpringSession的依赖

<!-- redis作为session的共享存储区域 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 整合SpringSession完成Session共享问题 -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>


②、配置文件上 配置redis作为session的存储类型

spring.session.store-type=redis

server.servlet.session.timeout=30m


③、主启动类上开启SpringSession功能

@EnableRedisHttpSession //整合redis作为session存储


④、增加配置类解决解决子域的session共享问题,以及使用JSON的序列化,序列化对象到redis中

@Configuration
public class GulimallSessionConfig {

    /**
     * @Description:  指定cookie的作用域,访问所有的子域和父域的域名时,都能携带这个cookie
     * @author  houChen
     * @date  2021/12/31 7:39
     */
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");
        cookieSerializer.setCookieName("GULISESSION");
        return cookieSerializer;
    }


    /**
     * @Description:  redis的序列化器
     * @author  houChen
     * @date  2021/12/31 7:41
     */
    @Bean
    public RedisSerializer<Object> SpringSessionDefaultRedisSerializer(){
        return  new GenericFastJsonRedisSerializer();
    }
}


⑥、正常在代码中使用session 即可

session.setAttribute("loginUser", data);


demo: https://gitee.com/houchen1996/gulimall 下的gulimall-auth-server

实现微博社交登录,用到了SpringSession,当微博登录后(auth.gulimall.com),gulimall.com item.gulimall.com服务下的页面都能取

到用户信息

posted @ 2022-01-02 17:14  青岑  阅读(129)  评论(0编辑  收藏  举报