使用SpringSession管理分布式系统的会话Session

在我方供应链项目分布式部署的环境下,需要在统一网关服务中管理访问的Session,即无论访问请求路由到哪一个网关服务环境,使用的都是相同的HttpSession,这样就保证了在用户登录之后,能够使用统一的Session来处理鉴权和其他逻辑,这对于分布式系统的用户会话管理是必要的。为了能够达到这个目的,我们引入了SpringSession。

SpringSession是什么

SpringSession是Spring框架大集合下的一个子组件,使用Redis来备份Web服务访问生成的(被加工过的)HttpSession,当你在使用SpringBoot框架的时候,你能够很方便的集成和使用它。

SpringSession如何使用

1、增加依赖

当你在使用SpringBoot框架并采用maven来管理依赖库时,你只需增加下面的依赖:

1 <dependencies>
2     <!-- ... -->
3
4     <dependency>
5         <groupId>org.springframework.session</groupId>
6         <artifactId>spring-session-data-redis</artifactId>
7     </dependency>
8 </dependencies>

幸运的是,当你在使用SpringBoot框架时,你不需要手动指定依赖的具体版本,它会帮你自动管理。

2、SpringBoot配置项

得益于SpringBoot的自动配置管理支持,在设置使用Redis备份SpringSession时,我们只需要在application.properties增加如下内容:

# Session store type.
spring.session.store-type=redis 

在如上的配置驱动下,我们再在SpringBoot的配置管理下增加@EnableRedisHttpSession注解,它会自动创建一个名称为SpringSessionReposityFilter且实现了Filter接口的(过滤器)类,这个过滤器将负责替换HttpSession的实现为SpringSession。

更多关于SpringSession的配置如下:

# Session timeout. If a duration suffix is not specified, seconds is used.
server.servlet.session.timeout= 

# Sessions flush mode.
spring.session.redis.flush-mode=on-save 

# Namespace for keys used to store sessions.
spring.session.redis.namespace=spring:session 

3、配置Redis连接

其实SpringBoot会自动创建一个叫做RedisConnectionFactory的类来管理SpringSession与Redis服务的连接,默认是连接到localhost端口为6379的Redis服务,但是在生产环境中,那就必须将这种与Redis服务器连接的配置进行自定义更改,你可以按照如下代码清单所例举的方式将配置追加到application.properties文件中:

# Redis server host.
spring.redis.host=localhost 

# Login password of the redis server.
spring.redis.password= 

# Redis server port.
spring.redis.port=6379 

当然,如果你的SpringBoot中自有管理与Redis服务器的连接,你同样可以在你的Configuration将这个连接复用给这里的配置,比如你使用JedisShardInfo。

以下是使用JedisShardInfo的代码参考:

 1 @Bean("jedisShardInfo")
 2 public JedisShardInfo jedisShardInfo(@Value("${jedis.redis.uri}") String uri,
 3                                      @Value("${catalog.redis.tesla}") String redisCatalog) {
 4     String redisUri = uri;
 5     redisUri = getRedisUri(redisCatalog, redisUri);
 6     return new JedisShardInfo(redisUri);
 7 }
 8
 9 private String getRedisUri(String redisCatalog, String redisUri) {
10     if(!StringUtils.isEmpty(redisCatalog)) {
11         log.info("===> Redis use unified configuration.");
12         DataSourceInstanceConfig dbInstanceConfig = DBLoader.getDataSourceInstanceConfig(redisCatalog);
13         RedisServerInfo serverInfo = dbInstanceConfig.getServer(RedisServerInfo.class).get(0);
14         redisUri = REDIS_URI_PREFIX.concat(serverInfo.getPassword()).concat("@")
15                 .concat(serverInfo.getHost()).concat(":")
16                 .concat(serverInfo.getPort()).concat("/")
17                 .concat(serverInfo.getDb());
18         log.info("===> redis_uri: {}", redisUri);
19     }
20     return redisUri;
21 }
22
23 @Configuration
24 @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 172800)
25 public class HttpSessionConfig {
26     @Bean
27     public static ConfigureRedisAction configureRedisAction() {
28         return ConfigureRedisAction.NO_OP;
29     }
30
31     @Bean
32     public JedisConnectionFactory connectionFactory(@Autowired @Qualifier("jedisShardInfo") JedisShardInfo jedisShardInfo){
33         return new JedisConnectionFactory(jedisShardInfo);
34     }
35 }

4、Servlet容器初始化

在SpringBootConfiguration的配置驱动下,自动创建的SpringSessionRepositoryFilter将负责替换系统的HttpSession为SpringSession并保存于redis中,为了这个拦截器能够发挥作用,Spring需要将这个过滤器纳入配置管理,最后我们还需要确保Servlet容器能够正确的使用这个拦截器拦截到所有请求,幸运的是,SpringBoot为我们顾及到了所有的这些步骤。

SpringSession的实现原理是什么

和我们使用Tomcat的HttpSession不同的是,我们将这个会话内容持久化到了Redis中。SpringSession将HttpSession替换为一种新的实现,并将它保存到了Redis中,也就是当我们的SpringSecurity的SecurityContextPersistenceFilter在保存了SecurityContext到HttpSession之后,就会触发这个替换机制保存到Redis中。

当我们发起访问请求的时候,系统会创建一个HttpSession,而SpringSesion会创建一个名称为SESSION的cookie放到你浏览器的中,这个cookie的内容包含了你session的ID,你可以在你的Chrome浏览器控制台中查看到。

于此同时,你也可以在你的redis服务器中看到,找到以application.properties中配置的命名空间开头的key值,然后你会看到包含和浏览器上看到的SESSION相同内容的key,当然你可以在redis服务器中使用redis-cli命令去查看或者删除它。

当你浏览器每次发起Http请求到服务端时,都会携带这个cookie内容,服务端SpringSession接受到这个cookie值之后就自动去redis中找到相同的会话Session,由此来识别出是同一个用户进行的访问。

参考资料

1、https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-redis.html

2、http://blog.didispace.com/spring-session-xjf-2/

原文地址:https://www.cnblogs.com/captainad/p/10861006.html

时间: 2024-10-07 00:06:27

使用SpringSession管理分布式系统的会话Session的相关文章

spring-session实现分布式集群session的共享

前言 HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的.但是我们把应用搭建成分布式的集群,然后利用LVS或Nginx做负载均衡,那么来自同一用户的Http请求将有可能被分发到多个不同的应用中.那问题来了,如何保证不同的应用能够共享同一份session数据呢?最简单的想法,就是把session数据保存到内存以外的一个统一的地方,例如Memcached/Redis等数据库中.那问题又来了,如何替换掉Servlet容器创建和管理的HttpSess

MyBatis之会话Session原理

MyBatis 之会话 Session 执行逻辑 1.SQL 会话工厂构建器类 SqlSessionFactoryBuilder 的 build 方法用于构建 SqlSessionFactory 类的实例: 2.SQL 会话工厂类的实例用于创建 Sql 会话 SqlSession 的实例: 3.SQL 会话 SqlSession 用于执行具体的 CURD 操作,其类似于 JDBC 中的连接类 Connection: 4.SQL 会话模板 SqlSessionTemplate 是 MyBatis

简单PHP会话(session)说明

现在程序员愈发的不容易了,想要精通,必然要寻本溯源,这其实与目前泛滥的愈发高级的语言以及众多的框架刚好相反,因为它们在尽可能的掩盖本源使其简单,个人称之为程序员学习悖论. 注:作者接触web开发和php两周左右,以下内容适合初学者. 1.导读 从文题目看,<简单PHP会话(Session)说明> 是已经圈定了本文的内容范围,试图阐明Session(文中对会话称为Session) 在PHP语言中是如何实现以及使用的,重点在于基本理解后的使用. 文章思路是首先搞清楚session是什么东西,Ses

webview HttpClient 怎么保持会话session统一

cookies session均为key---value的形式展示,  1.    session是存储在服务端,并有一块区域控件存储用户信息,主要是为了判断该用户是否登录,在客户端采用httpClient/HttpUrlConnection进行登录请求的时候,传过去的username=“ccc” 服务端中的session进行判断是否存在改sessionId,以及value,不存在代表改用户不曾登录,服务器会自动生成唯一的sessionId其为key,传过来的ccc则为value,key="se

浅谈IM软件业务知识—会话session的概念,附一张IM软件的层次图

session一般出现在计算机领域,IM软件中的session,老的IM有两层:首先是逻辑层的session来管理会话的参与者,消息列表,会话类型等等:还有协议层的session,主要是代表客户端跟服务器的一个事物通道. 老的IM软件 客户端跟Server交互的每一类操作都是基于会话.比如客户端登录,需要建立一个登录的会话:客户端发消息,需要建立一个会话.下面举例: 客户端向Server发了一条消息,这条消息的发送就建立在会话之上.客户端需要下面几个步骤. 1. 创建一个session ID=1

Android -- 与WEB交互在同一个会话Session中通信

Session与Cookie Cookie和Session都为了用来保存状态信息,都是保存客户端状态的机制,它们都是为了解决HTTP无状态的问题而所做的努力. Session可以用Cookie来实现,也可以用URL回写的机制来实现. Cookie和Session有以下明显的不同点: 1)Cookie将状态保存在客户端,Session将状态保存在服务器端: 2)Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器.网络服务器用HTTP头向客户端发送cookies,在客户

Oracle数据库的连接模式connection Mode、连接connection与会话session

数据库的连接模式Connection Mode: Dedicated Server Mode(专有模式) 当用户发出请求时,如远程的client端通过监听器连接数据库上,ORACLE的服务器端会启用一个进程来响应,ORACLE端进程和Client端进程通信组成一个会话,ORACLE进程帮用户发出SQL语句,将结果返回给用户. 一对一,一个用户进程对应一个服务器进程,响应很快,但如果用户比较多,数据库压力比较大. Share Server Mode 共享服务模式,通过一个分发起,把用户的请求发给服

jfc在jsp页面画图,不将图片存在服务器端,只存入会话session(可用)

jfc在jsp页面画图,不将图片存在服务器端,只存入会话session.其中主要用到jfc的一个servlet类. <%@ page contentType="text/html;charset=gb2312" errorPage="../common/error.jsp" %> <%@ page import="dqz.jsp.*" %> <%@ page import="java.sql.*"

重温WCF之会话Session(九)

转载地址:http://blog.csdn.net/tcjiaan/article/details/8281782 每个客户端在服务器上都有其的独立数据存储区,互不相干,就好像A和服务器在单独谈话一样,所以叫会话. 下面,我们写一个例子,看看在不支持会话的绑定上连续调用两个有关联的代码,会发生什么情况. [ServiceContract] public interface IService { [OperationContract(IsOneWay = true)] void SetValue(