spring boot 线程池_Spring集成redis实现分布式会话

9f1c64bb4f4447229f19b8a74f0208cb

在web项目开发过程中,会话通常用于存储一些业务中间数据、状态数据,是十分重要的一部分,在单机环境下这十分容易,但是在分布式的环境下,单机无法实现,就需要有一个完整的方案,目前业界常见的方案有两种:(1)Spring集成redis实现分布式会话(2)使用JWT(JSON Web Token)实现。

本文介绍在springboot环境下如何利用spring集成redis来实现分布式会话,并提供了相关代码和各项配置。

一、实现原理

将session id和session value以key-value的形式存于redis中,设置key的过期失效时间,当key值失效时就是session失效时。

二、引入依赖

如果你的应用是springboot应用并且使用了spring data,那么集成redis是十分简单的事情,因为redis已经提供了相关的依赖,而开发者只需要进行简单的配置即可。

    org.springframework.boot    spring-boot-starter-data-redis    org.springframework.session    spring-session-data-redis

三、添加配置

#session超时时间设置为1000秒server.session.timeout=1000#设置session的存储方式,none为存在本地内存中,redis为存在redis中spring.session.store-type=redis#namespace用于区分不同应用的分布式sessionspring.session.redis.namespace=demo#session更新到redis的模式,分为on_save和immediate,on_save是当执行执行完响应以后才将数据同步到redis,immediate是在使用session的set等操作时就同步将数据更新到redis,建议使用on_savespring.session.redis.flush-mode=on_save#redis配置,针对springboot2.X以下版本#redis的数据库,默认为0spring.redis.database=0#redis主机spring.redis.host=127.0.0.1#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 session

在spring入口应用上使用注解@EnableRedisHttpSession开启spring redis session。

//session失效时间设置为30分钟=1800秒@Configuration@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800,redisNamespace="test-service",redisFlushMode=RedisFlushMode.ON_SAVE)

4.1 配置事件通知

在有些情况下,应用程序需要监听到session实效,并且进行一些操作,例如记录用户退出时间,给用户发送一些通知等,在这种情况下,必须要能监听到redis中key值的实效。

当使用@EnableRedisHttpSession时,sessionMessageListener和redis KESPACE events将会被自动配置,这将在session失效时能够通知到应用,以便应用可以进行相关的操作。

值得注意的是,这个功能需要redis 2.8以上版本,并且开启事件通知 ,而事件通知在一般情况下都是关闭的,所以需要特别进行开启,方法有两种:

1.配置文件配置

notify-keyspace-events Egx

2.使用config命令

config set notify-keyspace-events Egx

若是不需要使用到session失效通知,可以加上以下配置:

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

4.2 配置监听线程池

Spring session监听默认采用的线程池是SimpleAsyncTaskExecutor,虽然名义上也是线程池,但是实际上每次请求都会创建新的线程,这在流量较大的情况下,如果响应较慢,大量请求将会导致出现大量的线程,容易导致OOM。一般情况下可以自行定义线程池,如下例子:

@Beanpublic ThreadPoolTaskExecutor threadPoolTaskExecutor(){    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();    executor.setCorePoolSize(10);    executor.setMaxPoolSize(30);    executor.setKeepAliveSeconds(30)    executor.setThreadNamePrefix("spring-redis-")    return executor;}

4.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头中,这是需要前端主动进行的操作,需要特别注意。

@Beanpublic 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;    }}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值