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

栏目: Java · 发布时间: 5年前

内容简介:如果你正在使用Java开发Web应用,想必你对HttpSession非常熟悉,但我们知道HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题。Spring Session提供了一套创建和管理Servlet HttpSession的方案,以此来解决Session共享的问题,更为重要的是在Spring Boot中使用它极其简单。HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。如果我们将Web应用横向扩展

前言

如果你正在使用 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的实现呢?

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

在Spring Boot中 集成 Spring Session

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

  1. 引入Maven依赖(本示例使用 dependencyManagement ,如果你没有使用它请添加 <version> 标签)
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session</artifactId>
        </dependency>
  1. 配置你的Spring Application,将你的 application.properties 加入以下配置。
spring.session.store-type=redis

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

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

我们来验证一下~

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

Debug,Http Session

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

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

Cookies

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://www.jianshu.com/p/e4191997da56

————-

3、Spring Session-使用Hazelcast的HttpSession

2017年09月19日 19:08:03 RonTech 阅读数:957

4.4. 使用Hazelcast的HttpSession

在使用HttpSession的任何功能之前通过添加一个Servlet过滤器,就可以启用Spring Session。

本节主要介绍基于Java配置如何使用Hazelcast支持HttpSession。

Hazelcast Spring样例提供了一个可执行的样例,这个样例提供了如何基于Java配置整合Spring Session和HttpSession。你可以阅读以下的一些基础步骤,但是当您与自己的应用程序整合时,推荐遵循详细的Hazelcast Spring参考指南。

4.4.1. Spring 配置

添加完成必要的依赖之后,我们需要创建我们自己的Spring配置,Spring配置负责创建一个Servlet过滤器,这个过滤器通过一个使用Spring Session支持的实现去替换HttpSession。添加如下的Spring配置:

@EnableHazelcastHttpSession 
@Configuration
public class HazelcastHttpSessionConfig {
    @Bean
    public HazelcastInstance hazelcastInstance() {
        MapAttributeConfig attributeConfig = new MapAttributeConfig()
                .setName(HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE)
                .setExtractor(PrincipalNameExtractor.class.getName());

        Config config = new Config();

        config.getMapConfig("spring:session:sessions") 
                .addMapAttributeConfig(attributeConfig)
                .addMapIndexConfig(new MapIndexConfig(
                        HazelcastSessionRepository.PRINCIPAL_NAME_ATTRIBUTE, false));
        return Hazelcast.newHazelcastInstance(config); 
    }
}
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. @EnableHazelcastHttpSession 注解创建了一个实现了Filter的名为springSessionRepositoryFilter 的Bean(过滤器),这个过滤器负责使用Spring Session支持的一个实现去替换HttpSession,这个实例中Spring Session由Hazelcast支持;
  2. 为了支持按principal name index检索会话,需要注册适当的ValueExtractor。Spring Session为此提供了PrincipalNameExtractor。
  3. 创建一个HazelcastInstance链接Spring Session和Hazelcast,默认情况下,一个嵌入的Hazelcast 默认实例会被启动并被应用所链接。关于更多配置Hazelcast的信息,可以参考 参考文档

4.4.2. Servlet容器初始化

Spring配置文件创建了一个实现了Filter的名为springSessionRepositoryFilter 的Bean,springSessionRepositoryFilter负责使用一个支持Spring Session的个性化实现替换HttpSession。

为了让我们的Filter发挥它的魔力,Spring需要加载我们的SessionConfig 类。由于我们的应用程序已经使用SecurityInitializer类加载了Spring配置,所以我们可以简单地添加我们的SessionConfig类。

src/main/java/sample/SecurityInitializer.java
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {

    public SecurityInitializer() {
        super(SecurityConfig.class, SessionConfig.class);
    }
}

最后我们需要确保Servlet容器(如Tomcat)的每个请求都使用了springSessionRepositoryFilter,非常重要的一点就是Spring Session的springSessionRepositoryFilter 必须在Spring Security’s springSecurityFilterChain之前被调用。这样就能够确保Spring Security使用的HttpSession也被Spring Session支持。幸运的是,Spring Session提供了一个很有效的名为AbstractHttpSessionApplicationInitializer的类,这个类会让实现以上的这些功能变得非常的容易。请看下面的例子:

src/main/java/sample/Initializer.java
public class Initializer extends AbstractHttpSessionApplicationInitializer {

}

我们自己的类(Initializer )的命名我们并不关心,最重要的是要继承AbstractHttpSessionApplicationInitializer。

继承AbstractHttpSessionApplicationInitializer 之后我们就能确保名为springSessionRepositoryFilter 的Spring Bean被注册到Servlet容器中,并且对于每一个请求的处理他都会处在Spring Security’s springSecurityFilterChain过滤器链中的所有过滤器之前。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Python

Programming Python

Mark Lutz / O'Reilly Media / 2006-8-30 / USD 59.99

Already the industry standard for Python users, "Programming Python" from O'Reilly just got even better. This third edition has been updated to reflect current best practices and the abundance of chan......一起来看看 《Programming Python》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具