在SpringBoot中使用Spring Session解决分布式会话共享问题

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> 在SpringBoot中使用Spring Session解决分布式会话共享问题

在SpringBoot中使用Spring Session解决分布式会话共享问题
作者:简单的土豆 www.jianshu.com/p/e4191997da56

在SpringBoot中使用Spring Session解决分布式会话共享问题

前言

如果你正在使用Java开发Web应用,想必你对HttpSession非常熟悉,但我们知道HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题。

Spring Session提供了一套创建和管理Servlet HttpSession的方案,以此来解决Session共享的问题,更为重要的是在Spring Boot中使用它极其简单。

Session共享的问题

HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。如果我们将Web应用横向扩展搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被负载分发到两个不同的实例中去,如何保证不同实例间Session共享成为一个不得不解决的问题。

最简单的解决方法就是把Session数据保存到内存以外的一个统一的地方,例如Memcached/Redis中。那么问题又来了,如何替换掉Servlet容器创建和管理HttpSession的实现呢?

  • 利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。不过这种方式有个缺点,就是需要耦合Tomcat/Jetty等Servlet容器的代码。这方面其实早就有开源项目了,例如memcached-session-manager,以及tomcat-redis-session-manager。暂时都只支持Tomcat6/Tomcat7。
  • 配置Nginx的负载均衡算法为ip_hash,这样每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的Session共享问题
  • 如果你使用Shiro管理Session,可以用Redis来实现Shiro 的SessionDao接口,这样Session便归Redis保管。
  • 设计一个Filter,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。Spring-Session就是通过这样的思路实现的。
  • 配置Nginx的负载均衡算法为ip_hash,这样每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的Session共享问题

    设计一个Filter,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。Spring-Session就是通过这样的思路实现的。

    在Spring Boot中 集成 Spring Session

    Spring Session 支持使用Redis、Mongo、JDBC、Hazelcast来存储Session,这里以Redis为例。

    1、引入Maven依赖(本示例使用dependencyManagement,如果你没有使用它请添加 version标签)

    
            dependency
                groupIdorg.springframework.boot/groupId
                artifactIdspring-boot-starter-data-redis/artifactId
            /dependency
            dependency
                groupIdorg.springframework.session/groupId
                artifactIdspring-session/artifactId
            /dependency
    

    2、配置你的Spring Application,将你的application.properties加入以下配置。

    
    spring.session.store-type=redis
    

    仅此两步,便集成完毕,整个过程完全无痛、无感~

    注意:如果你的Redis服务器不是使用本地默认配置(localhost:6379),需要配置你的Redis,如何配置?看这里。

    我们来验证一下~

    在SpringBoot中使用Spring Session解决分布式会话共享问题

    果然,Http Session已被Spring Session进行包装,我们可以依旧使用Http Session的API来进行编程。

    在SpringBoot中使用Spring Session解决分布式会话共享问题

    Cookies 也正常创建,Key为SESSION。

    
    127.0.0.1:6379 keys *
    1) "spring:session:sessions:083706a8-b2d8-480c-8b88-eafc798e7269"
    2) "spring:session:sessions:expires:083706a8-b2d8-480c-8b88-eafc798e7269"
    3) "spring:session:expirations:1490263320000"
    

    使用redis-cli查看,发现Redis中也已保存相关数据。

    参考

    https://link.jianshu.com/?t=http://docs.spring.io/spring-session/docs/current/reference/html5/

    END

    Java面试题专栏

    在SpringBoot中使用Spring Session解决分布式会话共享问题

    我知道你 “在看在SpringBoot中使用Spring Session解决分布式会话共享问题

    原文始发于微信公众号(Java知音):

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> 在SpringBoot中使用Spring Session解决分布式会话共享问题


     上一篇
    SpringBoot+AOP构建多数据源的切换实践 SpringBoot+AOP构建多数据源的切换实践
    针对微服务架构中常用的设计模块,通常我们都会需要使用到druid作为我们的数据连接池,当架构发生扩展的时候 ,通常面对的数据存储服务器也会渐渐增加,从原本的单库架构逐渐扩展为复杂的多库架构。 当在业务层需要涉及到查询多种同数据库的场景下
    下一篇 
    最详细的 Spring Boot 多模块开发与排坑指南 最详细的 Spring Boot 多模块开发与排坑指南
    来自:未读代码 创建项目创建一个 SpringBoot 项目非常的简单,简单到这里根本不用再提。你可以在使用 IDEA 新建项目时直接选择 Spring Initlalize 创建一个 Spring Boot 项目,也可以使用 Sprin