spring boot 及 redis 实现分布式session 实践笔记

(0)背景

Spring-Session实现Session共享入门教程

  1. Spring-Session使用的场景?

HttpSession是经过Servlet容器进行建立和管理的,在单机环境中。经过Http请求建立的Session信息是存储在Web服务器内存中,如Tomcat/Jetty。css

假如当用户经过浏览器访问应用服务器,session信息中保存了用户的登陆信息,而且session信息没有过时失,效那么用户就一直处于登陆状态,能够作一些登陆状态的业务操做!
单机sessionhtml

可是如今不少的服务器都采用分布式集群的方式进行部署,一个Web应用,可能部署在几台不一样的服务器上,经过LVS或者Nginx等进行负载均衡(通常使用Nginx+Tomcat实现负载均衡)。此时来自同一用户的Http请求将有可能被分发到不一样的web站点中去(如:第一次分配到A站点,第二次可能分配到B站点)。那么问题就来了,如何保证不一样的web站点可以共享同一份session数据呢?java

假如用户在发起第一次请求时候访问了A站点,并在A站点的session中保存了登陆信息,当用户第二次发起请求,经过负载均衡请求分配到B站点了,那么此时B站点可否获取用户保存的登陆的信息呢?答案是不能的,由于上面说明,Session是存储在对应Web服务器的内存的,不能进行共享,此时Spring-session就出现了,来帮咱们解决这个session共享的问题!web

集群session

  1. 如何进行Session共享呢?

简单点说就是请求http请求通过Filter职责链根据配置信息过滤器将建立session的权利由tomcat交给了Spring-session中的SessionRepository,经过Spring-session建立会话,并保存到对应的地方。redis

session共享

实际上实现Session共享的方案不少,其中一种经常使用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis,Mongo)中,spring

一句话总结——
DelegatingFilterProxy引导每一个请求到名为springSessionRepositoryFilter过滤器
RedisHttpSessionConfiguration建立名为springSessionRepositoryFilter 的Spring Bean,继承自Filter
springSessionRepositoryFilter替换容器默认的HttpSession支持为Spring Session
Spring Session将Session路由至redis


(一)spring boot 实现Redis实现分布式session功能的共享


spring boot 集成 redis-session:

实践测试:
有一个业务:
步骤一:获取验证码,服务端保存验证码在session上
步骤二:点击验证,服务端拿取session上的验证码与用户输入的做比较


首先在没有redis的状况下,步骤一指向服务器1,步骤二指向服务器2,原理上应该没法验证,由于session分布在两台服务器上,
实践结果与原理相同

而后在redis状况下,步骤一指向服务器1,步骤二指向服务器2,步骤1、二仍然应该连贯顺利进行,实践结果与原理相同

再,在redis状况下,步骤一指向服务器1,步骤二指向服务器2,步骤一进行后,删掉redis清空,步骤二应该没法验证,实践结果与原理相同

@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
 
}
 

若是须要添加失效时间可使用如下的写法:

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60) //1分钟失效
补充一下:
这个session的过时时间住了在注解上配置,也能够在java中设置的:
session.setMaxInactiveInterval(3 * 60);//3分钟失效
 

 
 
 
(二)9.30 出现问题: 

 
 

Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer'

 
 

根据提示,去相应的页面查看解决方案数据库

Firing SessionDeletedEvent or SessionExpiredEvent is made available through the SessionMessageListener which listens to Redis Keyspace events. In order for this to work, Redis Keyspace events for Generic commands and Expired events needs to be enabled. For example:浏览器

redis-cli config set notify-keyspace-events Egx

If you are using @EnableRedisHttpSession the SessionMessageListener and enabling the necessary Redis Keyspace events is done automatically. However, in a secured Redis enviornment the config command is disabled. This means that Spring Session cannot configure Redis Keyspace events for you. To disable the automatic configuration add ConfigureRedisAction.NO_OP as a bean.缓存

For example, Java Configuration can use the following:tomcat

@Bean
public static ConfigureRedisAction configureRedisAction() {
    return ConfigureRedisAction.NO_OP;
}

XML Configuration can use the following:

<util:constant
    static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
因此在redisconfig上注入bean

[java]  view plain  copy
  1. @Configuration  
  2. public class HttpSessionConfig {  
  3.     @Bean  
  4.     public static ConfigureRedisAction configureRedisAction() {  
  5.         return ConfigureRedisAction.NO_OP;  
  6.     }  
  7. }  

(三)原理简述

  1. 每次请求都经过NoSql数据库查询,若是存在,则获取值;反之存放值。  
  2. 我是经过redis来实现session的共享,其主要有一下两种方法:  
  3. 1、经过tomcat服务器的拓展功能实现  
  4.     这种方式比较简单,主要是经过继承session的ManagerBase类,实现重写session相关的方法,这种比较简单,  
  5.     参考源码连接(http://download.csdn.net/detail/fengshizty/9417242)。  
  6. 2、经过filter拦截request请求实现  
  7.     下面主要介绍这样实现方式:  
  8.     (1)写HttpSessionWrapper实现HttpSession接口,实现里面session相关的方法。  
  9.     (2)写HttpServletRequestWrapper继承javax.servlet.http.HttpServletRequestWrapper类,重写对于session  相关的方法。  
  10.     (3)写SessionFilter拦截配置的请求url,过去cookie中  
  11.     的sessionId,若是为空,对这次请求重写生成一个新的sessionId,在sessionId构造新的HttpServletRequestWrapper对象。  
  12.     (4)写SessionService实现session到redis的保存和过去,其key为sessionId,value为session对于的Map。  
  1.  

以上是常规实现的步骤,spring 帮咱们作了

增长配置类:

[java]  view plain  
  1. @EnableRedisHttpSession  
  2. public class HttpSessionConfig {  
  3.     @Bean  
  4.     public JedisConnectionFactory connectionFactory() {  
  5.             return new JedisConnectionFactory();  
  6.     }  
  7. }  
这个配置类有什么用呢?

官方文档:

The Spring configuration is responsible for creating a Servlet Filter that replaces the HttpSession implementation with an implementation backed by Spring Session. 

也就是说,这个配置类能够建立一个过滤器,这个过滤器支持Spring Session代替HttpSession发挥做用

The @EnableRedisHttpSession annotation creates a Spring Bean with the name of springSessionRepositoryFilter that implements Filter. The filter is what is in charge of replacing the HttpSession implementation to be backed by Spring Session. In this instance Spring Session is backed by Redis.

@EnableRedisHttpSession注解会建立一个springSessionRepositoryFilter的bean对象去实现这个过滤器。过滤器负责代替HttpSession。

也就是说,HttpSession再也不发挥做用,而是经过过滤器使用redis直接操做Session。

(四)redis的数据

key的简单介绍说明:

# 存储 Session 数据,数据类型hash
Keyspring:session:sessions:XXXXXXX

# Redis TTL触发Session 过时。(Redis 自己功能),数据类型:String
Keyspring:session:sessions:expires:XXXXX

#执行 TTL key ,查看剩余生存时间


#定时Job程序触发Session 过时。(spring-session 功能),数据类型:Set
Keyspring:session:expirations:XXXXX
取自:

Spring-Session实现Session共享入门教程


另有一片源码分析:

Spring Session解决分布式Session问题的实现原理

https://blog.csdn.net/xlgen157387/article/details/60321984

相关文章
相关标签/搜索