在单体应用的时代,Session 会话直接保存在服务器中,实现非常简单,但是随着微服务的流行,现代应用架构基本都是分布式架构,请求随机的分配到后端的多个应用中,此时session就需要共享,而存储在redis中就是一个最常用的方案之一。
springboot和spring data为集成redis提供了非常便捷的集成方法,可以轻松实现,本文一步一步介绍springboot如何集成redis,如何进行配置。
(关注我,及时获取更多技术干货)
一、引入依赖
如果你的应用是springboot应用并且使用了spring data,那么集成redis是十分简单的事情,应该redis已经提供了相关的依赖,而开发者只需要进行简单的配置即可。
<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>
二、详细配置
#session超时时间设置为1000秒 server.session.timeout=1000 #设置session的存储方式,none为存在本地内存中,redis为存在redis中 spring.session.store-type=redis #namespace用于区分不同应用的分布式session spring.session.redis.namespace=demo #session更新到redis的模式,分为on_save和immediate,on_save是当执行执行完响应以后才将数据同步到redis,immediate是在使用session的set等操作时就同步将数据更新到redis spring.session.redis.flush-mode=on_save #redis配置,针对springboot2.X以下版本 #redis的数据库,默认为0 spring.redis.database=0 #redis主机 spring.redis.host= #redis端口 spring.redis.port=6380 #redis密码 spring.redis.password= #连接池最大连接数,使用负值表示没有限制 spring.redis.pool.max-active=40 #连接池最大阻塞等待时间,使用负值表示没有限制 spring.redis.pool.max-wait=1000 #连接池中的最大空闲连接 spring.redis.pool.max-idle=5 #连接超时时间,单位毫秒 spring.redis.timeout=1000
三、使用spring redis session
在spring入口应用上使用注解@EnableRedisHttpSession开启spring redis session。
3.1 配置事件通知
当使用@EnableRedisHttpSession时,sessionMessageListener和redis KESPACE events将会被自动配置,这将在session失效时能够通知到应用,以便应用可以进行相关的操作。
值得注意的是,这个功能需要redis 2.8以上版本,并且开启事件通知 ,而事件通知在一般情况下都是关闭的,所以需要特别进行开启,方法有两种:
- 配置文件
notify-keyspace-events Egx
- 使用config命令
config set notify-keyspace-events Egx
若是不需要使用到session失效通知,可以取消这个自动配置
@Bean public static ConfigureRedisAction configureRedisAction(){ return ConfigureRedisAction.NO_OP; }
3.2 配置监听线程池
Spring session监听默认采用的线程池是SimpleAsyncTaskExecutor,虽然名义上也是线程池,但是实际上每次请求都会创建新的线程,这在流量较大的情况下,如果响应较慢,大量请求将会导致出现大量的线程,容易导致OOM。一般情况下可以自行定义线程池,如下例子:
@Bean public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(30); executor.setKeepAliveSeconds(30) executor.setThreadNamePrefix("spring-redis-") return executor; }
3.3 设置session Id传递方式
默认情况下session id通过cookie进行传递,但是有些浏览器不支持cookie,或者用户主动关闭了cookie,所以cookie的方式不是最稳妥的,spring redis提供了将session id放到请求头的方式,设置x-auth-token header头,对应的值就是session id,在首次请求以后spring会将x-auth-token放到header中,后续前端请求的时候需要继续将对应的session id放到header头中。
@Bean public HttpSessionStrategy httpSessionStrategy(){ return new HeaderHttpSessionStrategy(); }
综上整体的配置如下:
@SpringBootConfiguration @ConfigurationProperties(prefix="spring.session.custom.executor") public class SpringRedisSessionConfig(){ private Integer corePoolSize; private Integer maxPoolSize; private Integer keepAliveSeconds; private String threadNamePrefix; /*与HttpSessionListener两者选其一*/ @Bean public static ConfigureRedisAction configureRedisAction(){ return ConfigureRedisAction.NO_OP; } @Bean public HttpSessionListener httpSessionListener(){ return new HttpSessionListener(); } @Bean public ThreadPoolTaskExecutor threadPoolTaskExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(this.corePoolSize); executor.setMaxPoolSize(this.maxPoolSize); executor.setKeepAliveSeconds(this.keepAliveSeconds) executor.setThreadNamePrefix(this.threadNamePrefix) return executor; } @Bean public HttpSessionStrategy httpSessionStrategy(){ return new HeaderHttpSessionStrategy(); } public Integer getCorePoolSize(){ return corePoolSize; } public Integer getMaxPoolSize(){ return maxPoolSize; } public Integer getKeepAliveSeconds(){ return keepAliveSeconds; } public String getThreadNamePrefix(){ return threadNamePrefix; } }