SpringSession 简单使用

楔子

学习笔记 ,做个记录

session 共享问题解决

1 session复制

  • 优点

    tomcat 原生支持,只需要修改配置文件

  • 缺点

    1. session 同步需要数据传输,占用大量网络带宽,降低了服务器群的业务处理能力
    2. 任意一台web-server保存的数据都是所有web-server的session总和,收到内存限制无法水平扩展更多的web-server
    3. 大型分布式集群情况下,由于所有web-server都全量保存数据,所有次方案不可取

2 hash一致性

  • 优点

    1. 只需要该nginx配置,不需要修改应用代码
    2. 负载均衡,只要hash属性的值分布式均匀的,多台web-server的负载是均衡的
    3. 可以支持web-server水平扩展(session同步是不行的,受内存限制)
  • 缺点

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

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

3 统一存储

  • 优点
    1. 没有安全隐患
    2. 可以水平扩展,数据库/缓存水平切分即可
    3. web-server重启或扩容都不会丢失
  • 不足
    1. 增加了一次网络调用,并且需要修改相应的代码,如将所有的getSession方法替换为从Redis查数据的方式,redis获取数据比内存慢很多。
    2. 上面的缺点可以用springSession完美解决。

4 session共享问题解决-不同服务,子域session共享|(springSession)

SpringSession 简单使用

在这里插入图片描述
以下使用Redis作为存储session的介质

1 pom引入依赖

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

# springboot启动类加注解
@EnableRedisHttpSession

代码中处理

@Slf4j
@RestController
@RequestMapping("/session")
public class SessionController {


    @RequestMapping("login")
    public String login(HttpServletRequest req, HttpServletResponse resp, HttpSession session,
                        User user) {
        //TODO 1 默认发的令牌,SESSION=*** ,作用域:当前域(解决子域共享)
        //TODO 2使用JSON的序列化存储数据到 Redis
        log.info("login user is {}", user);
        session.setAttribute(SysUtils.LOGIN_NAME, user);
        return String.format("%s|%s|", SysUtils.getDateSpan(), user.getUname());
    }

    @RequestMapping("show")
    public Object showLoginUser(HttpSession session) {
        Object attribute = session.getAttribute(SysUtils.LOGIN_NAME);
        log.info("获取的session user is {}", JSON.toJSONString(attribute));
        return attribute;
    }
}

设置Redis存储为JSON以及配置子域共享

@Configuration
public class SessionConfig {

    /**
     * 设置热session cookie name 以及子域共享
     *
     * @return
     */
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer serializer = new DefaultCookieSerializer();

        serializer.setCookieName("WEBJSESSIONID");
        serializer.setCookiePath("/");
        serializer.setDomainName("grq.com");
        //serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
        return serializer;
    }
    /**
     * 设置redis session 序列化方式为JSON
     *
     * @return
     */
    @Bean
    public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
        //return new FastJsonRedisSerializer();
        //return new GenericFastJsonRedisSerializer();
        return  new GenericJackson2JsonRedisSerializer();
    }
}

**域名和子域名使用Windows hosts模拟 **

3 配置文件

配置存储方式为redis,以及redis配置

################################ session
spring.session.store-type=redis
# more就是30分钟
server.servlet.session.timeout=30m
################################ session |end
#redis
spring.redis.host=127.0.0.1
spring.redis.port=6379

Redis存储
在这里插入图片描述
**域名 使用SwitchHosts! 添加模拟 **
在这里插入图片描述

遇到的问题

使用fastjson 作为序列化 JSON的时候,出现了**NoSuchMethodError: com.alibaba.fastjson.serializer.JavaBeanSerializer.processValue**

https://github.com/alibaba/fastjson/issues/2780
需要升级 将fastjson从1.2.57升级到1.2.61

发布了308 篇原创文章 · 获赞 70 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/u012848709/article/details/105564537