session 共享

session原理

在这里插入图片描述

  1. 用户使用浏览器第一次登录服务器成功后,服务器会创建 session 保存用户相关信息
  2. 接着服务器命令浏览器保存一个 jsessionid(作用域默认为当前访问服务器的域名),该jsessionid用于之后访问服务器时,拿到保存在 session 中的相关信息
  3. 再次访问服务器时,携带jsessionid,无需登录。因为根据jsessionid可以取到相关 session 信息
  4. 如果关闭浏览器,并清除 cookie(jsessionid保存再cookie中),再次向服务器发起访问时,这时候由于没有 jsessionid ,需要转到步骤1,重写发起登录。

分布式环境下,session 不共享问题

  1. 同域名下 session 不能共享问题
    在这里插入图片描述
  2. 不同域名下,session 不能共享问题
    在这里插入图片描述

分布式环境下,解决 session 共享问题

同域名下 session 共享问题解决
  • 方案1,session 复制
    在这里插入图片描述

    优点:tomcat 原生支持 session复制,只需要修改配置文件即可
    缺点:

    1. session同步需要数据传输,占用大量网络带宽,降低服务器的业务处理能力
    2. 需要较多内存,无法水平扩展更多的 web-server。因为每台 web-server 都需要存储所有 session数据
  • 方案2,客户存储 session (这种方式不会使用,提供一种思路)
    在这里插入图片描述

    优点:服务器不需要存储 session,用户保存自己的 session 信息到 cookie 中,节省服务器资源
    缺点:

    1. 每次 http 请求都需要携带 cookie中的完整信息,浪费网络带宽
    2. cookie长度有 4k限制,所有 session不能太长
    3. session 数据存放在cookie中,存在泄漏,篡改,窃取等安全隐患
  • 方案3,一致性hash
    在这里插入图片描述

    优点:

    1. 只需要配置 nginx,不需要修改代码
    2. 只要被hash的字段字分布均匀,那么每台web-server的负载就是均衡的
    3. 可以支持web-server水平扩展

    缺点:

    1. session 存在web-server 中,web-server 重启导致部分 session 丢失,影响业务。如部分用户需要重写登录
    2. web-server水平扩展后,rehash后session重写分布,也会有部分用户路由不到正确的 session,因此需要重写登录

    这些缺点的问题不大,因为session本来就是有有效期的。因此这种反向代理方式可以使用。

  • 方案4, 统一存储到DB或者Redis中
    在这里插入图片描述

    优点:

    1. 没有安全隐患
    2. 可以水平扩展
    3. web-server重启或者扩容,都不会有session丢失

    缺点:

    1. 增加了一次网络调用,需要修改业务代码,如将所有的 getSession 方法替换为从Redis中查询数据
    2. 从 redis 获取数据比从内存中慢

    上面的缺点,可以用 SpringSession解决

不同域名下,session 共享问题

在这里插入图片描述

  1. 访问商品服务完成后,服务器命令浏览器保存 jsessionid 到 mall.com 域名下,(默认保存会保存在product.mall.com域名下,服务可以将jsessionid的作用域放大到父级域名 mall.com)
  2. 访问订单服务,此时会携带jsessionid,因为 order.mall.com 域名为 mall.com 域名的子域名,而jsessionid保存在 mall.com域名下,因此,访问 mall.com下的所有子域名,都会携带jsessionid。

如此,解决不同子域名下,session共享问题。

分布式情况下,使用 SpringSession 实现同域名和不同子域名 session 共享

参考 https://docs.spring.io/spring-session/docs/2.5.1/reference/html5/#httpsession-redis

  1. 添加依赖
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    
  2. application.yml文件中配置
    spring:
      session:
        store:
          type: redis
    # 调整 session 的过期时间      
    server:
      servlet:
        session:
          timeout: 30m
    
  3. Spring Boot 帮我自动创建了 springSessionRepositoryFilter

    Our Spring Boot Configuration created a Spring bean named springSessionRepositoryFilter that implements Filter. The springSessionRepositoryFilter bean is responsible for replacing the HttpSession with a custom implementation that is backed by Spring Session.

  4. 添加注解 @EnableRedisHttpSession 确保 SpringSession 来管理 HttpSession
  5. 自定义cookie,修改 session的作用域
    /**
     * 该类放入两个bean到spring容器中
     * 1. 主要解决session作用域问题
     * 2. 解决session存储到redis中,修改默认的存储方式
     */
    @Configuration
    public class MallSessionConfig {
    
        /**
         * 自定义cookie,因为cookie是存储在客户端的。
         * 为了解决session子域共享问题,我们自定义存储cookie的时候,
         * 修改cookie的默认作用域,将cookie的作用域放大到父级别的域名
         *
         * @return
         */
        @Bean
        public CookieSerializer cookieSerializer() {
            DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();
            defaultCookieSerializer.setDomainName("mall.com");
            defaultCookieSerializer.setCookieName("MALLSESSION");
            return defaultCookieSerializer;
        }
    
        /**
         * 修改默认的序列化机制,默认采用jdk序列号机制,
         * 这里让存在redis中的数据为json数据,而不是
         * 使用jdk序列化后的数据
         * @return
         */
        @Bean
        public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
            return new GenericFastJsonRedisSerializer();
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值