谷粒商城Session原理和分布式SpringSession项目结合

28 篇文章 20 订阅 ¥19.90 ¥99.00
本文介绍了在分布式环境中Session面临的挑战,如跨域和数据同步问题,并详细阐述了解决这些问题的四种策略,包括使用SpringSession。通过配置SpringSession,实现Session数据存储到Redis,解决了子域共享和序列化问题。同时,探讨了SpringSession的核心原理,涉及RedisOperationsSessionRepository和RedisRepositoryFilter的使用。
摘要由CSDN通过智能技术生成

 原始的非分布式Session原理

        Session其实就是服务器的内存数据,其实他的底层就是一个Map 。

工作原理:Session会为每一个用户创建一个Session对象.创建Session对象后,会将其对应的数据存到session中,给浏览器返回一个jsessionid,这个jessionid就是对应用的里面存储的数据。

在分布式中Session中遇到的问题

第一个问题:不同域名下,浏览器存储的jsessionid是没有存储的

第二个问题:也就是Session共享问题,即使域名相同,但是分布式的服务在相同的服务里面有多个服务集群部署的,用户每次访问的时候,不能总是访问同一个服务,可能到了其他的服务,而其他的服务是没有存储session里面的数据,这里就需要考虑session同步的问题,就是处理同一个模块下的,多个集群服务里面的session的数据要保持同步。

 

第一个问题:

 看下面的两个图,auth.gulimall.com域名和gulimall.com域名对应的存储JESESSIONID。当用户登录后,gulimall.com域名下是没有存储的。

 

第二个问题情况

一个模块部署多个服务器,但是能确保用访问的是同一个模块下对应服务的session吗,可能访问的是同一个模块的下没有的存储session的服务。

解决上面的两个问题

下面的是解决问题二的方式:

解决Session共享问题。使用Session复制方法

第一种方式:配置tomcat

这种的只适用于3-5个tomcat服务的时候,可以使用,在分布式情况下不适合的。

存在的问题:带宽问题,相互同步需要消耗网络传输时间。tomcat内存问题,每一个tomcat都要存储其他tomcat对应的数据消耗内存。

第二种方式:

在客户端将所有的数据存储到cookie中,但是这是存在安全隐患的对应的数据可以被修改,而且cookie存储的数据是有限的只有4K。这种一般不用

第三种方案:

选择hash一致性,也就是用户访问的时候,总是访问同一个服务。这里是修改nginx的配置,也可以结合业务字段,sid是456就到另一台服务器,其他的到另外一台服务器。

第四种方式:

使用公共的区域进行存储session,比如redis,数据库或者存储的更快的非关系型数据库。

 下面是解决问题一的问题

解决子域共享问题

用户通过浏览器登录会员服,会员服务会将其对应的用户信息存储到内存session中,但是这里我不将其用户的信息存储内存session中,我们将其对应的用户的信息存储到redis。接下来给浏览器发卡,我们将其对应的域名放大,这样对应的子域名也可以可以访问对应的域名放大的jessionid里面的数据。

引入SpringSession和使用:

需要注意SpringSession有自动延期:redis中的数据也是有过期时间

官网2.2.1.RELEASE文档:https://docs.spring.io/spring-session/docs/2.2.1.RELEASE/reference/html5/#samples

java配置文档:https://docs.spring.io/spring-session/docs/2.2.1.RELEASE/reference/html5/#httpsession-redis-jc

如何使用:注意,哪里需要SpingSesson,哪里就需要配置。都要配置

添加依赖



<dependencies>
	<!-- ... -->

	<dependency>
		<groupId>org.springframework.session</groupId>
		<artifactId>spring-session-data-redis</artifactId>
	</dependency>
</dependencies>

 配置文件中添加配置

spring.session.store-type=redis # Session store type.


#下面的是配置可以不加,这里可以添加一个过期时间
server.servlet.session.timeout= # Session timeout. If a duration suffix is not specified, seconds is used.
spring.session.redis.flush-mode=on-save # Sessions flush mode.
spring.session.redis.namespace=spring:session # Namespace for keys used to store sessions.

 开启注解。EnableRedisHttpSession注解。

 

注意下面的配置,这个是用来解决序列化转Json,

​


@Configuration
public class GulimallSessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");//放大整个系统域的作用域
        cookieSerializer.setCookieName("GULISESSION");
        return cookieSerializer;
    }

    /**
     * 序列化机制
     * @return
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

[点击并拖拽以移动]
​

补充:

也可以直接放在配置文件中添加配置。

运行项目会发现报异常出现序列化异常,对应的MemberRespVo没有进行序列化

修改实体类

运行后查看redis确实存在session

 效果展示:

 随便访问一个域名

 发现上面的对应Domain的域名是子域名,对于其他的域名是访问不到,这里先手动的修改一下域名。

将其对应的两个cookie的域名都手动放大。

 访问gulimall.com的时候,会发现父域里面用到了这两个令牌,也是可以访问到之前手动修改的,如果想去对应redis中存储的session里面的数据,就需要在product服务中配置SpringSession.

下面的是prodcut服务中配置SpringSession 的相关配置。

添加依赖

  <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

 配置相关配置

spring.session.store-type=redis

开启相关注解

从页面中获取

运行后发现反序列化不过来

 

 查看商品服务的错误

发现其实是认证服务里面有这个对象,商品服务没有这个对象。可以将其这个对象存储到comm服务中。

运行的时候如果还是出现这个对象的问题,就将其redis中存储的数据都清除掉。

重新进行用户登录

会发现gulimall.com里面什么都没有,这是为什么,看下面访问auth.gulimall.com的里面的domain他的域名是auth.gulimall.com,如果将其域名放大,这个gulimall.com就能看对应的co

 

登录成功后:查看redis

 下面手动的进行放大域名,对其auth.gulimall.com进行域名放大

 在此查看gulimall.com对应的cookie里面就会有数据。

 综合上面的情况SpringSession还要处理的两个问题

第一个问题:如何放大作用域

第二个问题:每次需要继承Serializable,比较麻烦。可以使用序列化器。进行转换成json

查看SpringSession相关配置官网:https://github.com/spring-projects/spring-session/tree/2.2.1.RELEASE/spring-session-samples/spring-session-sample-boot-redis-json/src/main/java/sample/config

设置Cookie序列化器:https://docs.spring.io/spring-session/docs/2.2.1.RELEASE/reference/html5/#api-cookieserializer

下面的是配置就是解决上面的两个问题:


@Configuration
public class GulimallSessionConfig {
    @Bean
    public CookieSerializer cookieSerializer(){
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setDomainName("gulimall.com");//放大整个系统域的作用域
        cookieSerializer.setCookieName("GULISESSION");
        return cookieSerializer;
    }

    /**
     * 序列化机制
     * @return
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }
}

 下面进行运行

 

 SpringSession的核心原理:

两个组件:

第一个组件:RedisOperationsSessionRepository:进行redis的操作Session的增删改查。

第二个组件:RedisRepositoryFilter   相当于Filter:操作session存储的过滤器

下面的代码是第二个组件的介绍,就是给request和response进行重新包装

 

需要注意SpringSession有自动延期:redis中的数据也是有过期时间

/*
 * SpringSession的核心原理利用了装饰者模式
 *@EnableRedisHttpSession导入了RedisHttpSessionConfiguration
 *给容器中添加了一个组件  RedisOperationsSessionRepository:进行redis的操作
 *还有一个组件RedisRepositoryFilter   相当于Filter:操作session存储的过滤器
 *创建的时候,就自动从容器中获取到RedisOperationsSessionRepository
 * 原始的request,response都被包装,SessionRepositoryRequestWrapper SessionRepositoryResponseWrapper
 * 以后获取session,request.getsession使用
 * wrappedRequest.getsession====>通过RedisOperationsSessionRepository操作redis获取session
 *
 *
 *
 * 自动延期:redis中的数据也是有过期时间
 * */

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

越来越没意思

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值