Spring-Session实现session共享原理及解析

写在前面

Session简介

是什么?

Session在网络中表示“会话控制”,用于存储特定用户所需的属性和其他的配置信息;Session表示一个特定的时间间隔,可以指用户从登陆系统到注销退出系统之家的时间。

为什么出现?

因为http 是一种无状态协议,如果没有Session的话,服务器无法识别请求是否来自同一个用户!在一些业务场景中需要知道前面的操作和后台的操作是不是同一个用户的行为,即业务之间是有关联性的。

怎么用?

使用Session结合浏览器Cookie,将服务器Session保存到浏览器cookie中,这样可以保持http会话状态。

Session服务器创建,如Tomcat,浏览器发起请求到Tomcat服务器,然后Tomcat服务器生成SessionId保存在内存中,并将SessionId返回给浏览器,浏览器通过Cookie保存SessionId信息,用户每次通过浏览器访问服务器都会带上SessionId信息,这样就可以判断每次的请求是不是同一个用户,解决http协议无状态问题。

前言

公司现在业务服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不同的服务器上,通过Nginx等进行负载均衡(一般使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的Http请求将有可能被分发到不同的Web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。分布式使用Nginxt实现负载均衡,最常用的均衡算法有IP_Hash、轮训、根据权重、随机等。不管对于哪一种负载均衡算法,由于Nginx对不同的请求分发到某一个Tomcat,Tomcat在运行的时候分别是不同的容器里,因此会出现Session不同步或者丢失的问题。那么问题就来了,如何保证不同的Web站点能够共享同一份Session数据呢?

实际上,实现Session共享的方案很多,最简单的想法就是把session数据保存到内存以外的一个统一的地方,例如MongoDB/Redis等数据库中,那么问题又来了,如何替换掉Servlet容器创建和管理HttpSession的实现呢?

这里我们就可以引入一个新的框架来接管会话的session数据,那么,Spring-Session就应运而生了。

实现原理简单介绍

Spring-Session的实现就是设计一个过滤器Filter,当Web服务器接收到http请求后,当请求进入对应的Filter进行过滤,利用HttpServletRequestWrapper,实现自己的 getSession()方法,接管创建和管理Session数据的工作。将原本需要由web服务器创建会话的过程转交给Spring-Session进行创建,本来创建的会话保存在Web服务器内存中,通过Spring-Session创建的会话信息可以保存第三方的服务中,如:redis,mysql等。Web服务器之间通过连接第三方服务来共享数据,实现Session共享!

当然,我们也可以通过其他方法实现接管创建和管理Session数据的工作,可以利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略。不过这种方式有个缺点,就是需要耦合Tomcat/Jetty等Servlet容器的代码。这方面其实早就有开源项目了,例如 memcached-session-manager,以及 tomcat-redis-session-manager。暂时都只支持Tomcat6/Tomcat7。这里我们将学习应用最为广泛的Spring-Session。

Spring-Session官网地址:Spring Session

Spring-Session官方文档:Spring Session

Spring Session特性

下面是来自官网的特性介绍:Spring Session提供了一套创建和管理Servlet HttpSession的方案。Spring Session提供了集群Session(Clustered Sessions)功能,默认采用外置的Redis来存储Session数据,以此来解决Session共享的问题。

Spring Session提供以下特性:

  • API和用于管理用户会话的实现;
  • 允许以应用程序容器(即Tomcat)中性的方式替换HttpSession;
  • Spring Session 让支持集群会话变得不那么繁琐,并且不和应用程序容器金习性绑定到。
  • Spring 会话支持在单个浏览器实例中管理多个用户的会话。
  • Spring Session 允许在headers 中提供会话ID以使用RESTful API。

集成Spring Session的正确姿势

springboot整合redis集成spring-session非常的方便,这也是springboot的宗旨,简化配置。

(1)第一步,添加Maven依赖

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

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

(2)第二步,配置redis

在application.properties中配置redis

# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=

(3)第三步,编写一个配置类

用来启用RedisHttpSession功能,并向Spring容器中注册一个RedisConnectionFactory,同时将RedisHttpSessionConfig加入到容器中

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisHttpSessionConfig {
}

还可以把该注解@@EnableRedisHttpSession注解加在启动类的上面。

一、Spring Session原理

前面集成spring-sesion的最后一步中,编写了一个配置类RedisHttpSessionConfig,它包含注解@EnableRedisHttpSession,@EnableRedisHttpSession注解通过Import引入了RedisHttpSessionConfiguration配置类。该配置类通过@Bean注解,向Spring容器中注册了一个SessionRepositoryFilter(SessionRepositoryFilter的依赖关系:SessionRepositoryFilter --> SessionRepository --> RedisTemplate --> RedisConnectionFactory)。

SessionRepositoryFilter这个过滤器的主要作用是拦所有的请求,接管创建和管理Session数据。具体怎样接管session数据我们后边讲,我们现在只需要了解SessionRepositoryFilter整个过滤器作用就行。

RedisHttpSessionConfiguration继承了SpringHttpSessionConfiguration,SpringHttpSessionConfiguration中进行了SessionRepositoryFilter的注册,代码如下:


                
  • 28
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值