好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

待解决的问题

spring session(redis存储方式)监听导致创建大量redismessagelistenercontailner-x线程

解决办法

为spring session添加springsessionredistaskexecutor线程池。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

/**

  * 用于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):

?

1

2

3

4

5

6

7

@autowired (

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

)

@qualifier ( "springsessionredistaskexecutor" )

public void setredistaskexecutor(executor redistaskexecutor) {

   this .redistaskexecutor = redistaskexecutor;

}

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

题外话

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

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

它创建了simpleasynctaskexecutor

说回redishttpsessionconfiguration,我们接着看:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

@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 = true ;

}

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线程问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

原文链接:https://www.cnblogs.com/aoeiuv/p/9565617.html

查看更多关于解决Spring session(redis存储方式)监听导致创建大量redisMessageLis的详细内容...

  阅读:42次