为什么说SpringSession不适合用户量大的场景,你看看这个默认配置!!

2023-10-25 12:37:25 浏览数 (1)

  • 出现CPU利用率异常了

  • 原因:SpringSession的默认配置不合理导致
  • 解决办法
  • 小结

背景:出现异常了

发现应用的CPU利用率持续大于90%,且存在CPU热点。 查看监控,发现“线程创建销毁”指标不正常:

正常的应该是这样的:

创建线程是耗时耗资源的操作,一般都会使用线程池来。看上面的数据,同一个时间点,创建的线程数和销毁的线程数在同一个数据量级,很可能是new Thread方式创建的线程执行耗时较短的,然后马上被GC回收引发。不像是使用了线程池。

原来是你啊:springSessionRedisMessageListenerContailner-X

springSessionRedisMessageListenerContailner-X 线程是干什么的?

先来回顾一下SpringSession的事件驱动机制:

SpringSession基于Redis的Pub/Sub能力,通过RedisMessageListenerContainer来实现了Sesssion事件机制。 在spring-session-data-redis 2.5.6中, RedisMessageListenerContainer承载了三类事件: Session创建事件: [SessionCreatedEvent] Session删除事件: [SessionDeletedEvent] Session过期事件: [SessionExpiredEvent]

springSessionRedisMessageListenerContailner-X线程在SpringSession的事件机制是干活的。是worker线程。

org.springframework.session.data.redis.config.annotation.web.http. RedisHttpSessionConfiguration #springSessionRedisMessageListenerContainer

org.springframework.data.redis.listener. RedisMessageListenerContainer #afterPropertiesSet

org.springframework.data.redis.listener. RedisMessageListenerContainer #createDefaultTaskExecutor

org.springframework.data.redis.listener.RedisMessageListenerContainer#dispatchMessage

org.springframework.util.CustomizableThreadCreator#createThread

通过debug,问题已经搞清了:SpringSession的事件机制默认使用SimpleAsyncTaskExecutor来execute监听事件任务。 默认情况下,SimpleAsyncTaskExecutor通过new Thread来管理执行任务的worker线程。

怎么解决?

org.springframework.session.data.redis.config.annotation.web.http. RedisHttpSessionConfiguration #setRedisTaskExecutor

代码语言:javascript复制
    /**
     * 用于spring session,防止每次创建一个线程
     *
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor springSessionRedisTaskExecutor() {
        ThreadPoolTaskExecutor springSessionRedisTaskExecutor = new ThreadPoolTaskExecutor();
        springSessionRedisTaskExecutor.setCorePoolSize(30);
        springSessionRedisTaskExecutor.setMaxPoolSize(100);
        springSessionRedisTaskExecutor.setKeepAliveSeconds(60);
        springSessionRedisTaskExecutor.setQueueCapacity(1000);
        springSessionRedisTaskExecutor.setDaemon(true);
        springSessionRedisTaskExecutor.setThreadNamePrefix("s-s-e");
        return springSessionRedisTaskExecutor;
    }

Bean名必须是springSessionRedisTaskExecutor

将项目重新发版上线后,问题没有再出现。

小结

通过以上的分析和处理,我们成功地解决了SpringSession默认配置导致的CPU异常问题。这个过程中,我们深入理解了SpringSession的工作原理和配置方式,也学习了如何有效地解决CPU异常的问题。

总的来说,虽然这个问题给我们带来了一些困扰,但也让我们收获了很多。我们将继续努力,提高我们的技术能力和解决问题的能力,以便在未来的开发过程中,能够更好地应对各种问题。

0 人点赞