解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner

网友投稿 750 2023-01-22


解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner

待解决的问题

Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程

解决办法

为spring session添加springSessionRedisTaskExecutor线程池。

/**

* 用于spring session,防止每次创建一个线程

* @return

*/

@Bean

public ThreadPoolTaskExecutor springSessionRedisTaskExecutor(){

ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();

springSessionRedisTaskExecutor.setCorePoolSize(8);

springSessionRedisTaskExecutor.setMaxPoolSize(16);

springSessionRedisTaskExecutor.setKeepAliveSeconds(10);

springSessionRedisTaskExecutor.setQueueCapacity(1000);

springSessionRedisTaskExecutor.setThreadNamePrefix("Spring session redis executor thread: ");

return springSessionRedisTaskExecutor;

}

原因

在Spring Session(redis)的配置类源码中(RedisHttpSessionConfiguration):

@Autowired(

required = false //该处理监听的线程池不是必须的,如果不自定义默认将使用SimpleAsyncTaskExecutor线程池

)

@Qualifier("springSessionRedisTaskExecutor")

public void setRedisTaskExecutor(Executor redisTaskExecutor) {

this.redisTaskExecutor = redisTaskExecutor;

}

springSessionRedisTaskExecutor不是必须的,如果不自定义则spring默认将使用SimpleAsyncTaskExecutor线程池。

题外话

SimpleAsyncTaskExecutor:每次都将创建新的线程(说是“线程池”,其实并非真正的池化,但它可以设置最大并发线程数量。)

@EnableAsync开启异步方法,背后默认使用的就是这个线程池。使用异步方法时如果业务场景存在频繁的调用(该异步方法),请自定义线程池,以防止频繁创建线程导致的性能消耗。如果该异步方法存在阻塞的情况,又调用量大,注意有可能导致OOM(线程还未结束,又增加了更多的线程,最后导致内存溢出)。@Async注解可以选择使用自定义线程池。

它创建了SimpleAsyncTaskExecutor

说回RedisHttpSessionConfiguration,我们接着看:

@Bean

public RedisMessageListenerContainer redisMessageListenerContainer() {

RedisMessageListenerContainer container = new RedisMessageListenerContainer();

container.setConnectionFactory(this.redisConnectionFactory);

if (this.redisTaskExecutor != null) {

container.setTaskExecutor(this.redisTaskExecutor);

}

if (this.redisSubscriptionExecutor != null) {

container.setSubscriptionExecutor(this.redisSubscriptionExecutor);

}

container.addMessageListener(this.sessionRepository(), Arrays.asList(new PatternTopic("__keyevent@*:del"), new PatternTopic("__keyevent@*:expired")));

container.addMessageListener(this.sessionRepository(), Collections.singletonList(new PatternTopic(this.sessionRepository().getSessionCreatedChannelPrefix() + "*")));

return container;

}

RedisMessageListenerContainer正是处理监听的类,RedisMessageListenerContainer设置了不为空的redisTaskExecutor,因为spring session默认没有配置该Executor,那RedisMessageListenerContainer在处理监听时怎么使用线程呢?我们接着看RedisMessageListenerContainer的源码:

public void afterPropertiesSet() {

if (this.taskExecutor == null) {

this.manageExecutor = true;

this.taskExecutor = this.createDefaultTaskExecutor();

}

if (this.subscriptionExecutor == null) {

this.subscriptionExecutor = this.taskExecutor;

}

this.initialized = truegKCqbbnbK;

}

protected TaskExecutor createDefaultTaskExecutor() {

String threadNamePrefix = this.beanName != null ? this.beanName + "-" : DEFAULT_THREAD_NAME_PREFIX;

return new SimpleAsyncTaskExecutor(threadNamePrefix);

}

afterPropertiesSet()这个方法熟悉吧,这个方法将在所有的属性被初始化后调用(InitializingBean接口细节这里不再赘述)。

所以如果用户没有定义springSessionRedisTaskExecutor,Spring session将调用createDefaultTaskExecutor()方法创建SimpleAsyncTaskExecutor线程池。而这个“线程池”处理任务时每次都创建新的线程。所以你会发现很多个redisMessageListenerContailner-X线程。

总结

以上所述是给大家介绍的解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spark MLlib随机梯度下降法概述与实例
下一篇:java实现自动回复聊天机器人
相关文章

 发表评论

暂时没有评论,来抢沙发吧~