背景
1. springboot为:2.1.2.RELEASE
2. 在max-busi-consumer服务的jar包实例下有多个队列的消费者(center-unload-persist、site-send、...)每个队列对应的消费者数有大于1个以上消费者(concurrency > 1)
现象
部分队列的消费者数量未匹配到指定的消费者concurrency值
多次重启后发现缺失消费者数量的总为固定的几个队列的消费者
获取到托管到spring中的bean列表发现,缺失消费者的bean在所有队列消费者最后托管
定位
1. 查阅资料知道;多个queue的consumer会共用taskExecutor的线程池数量,如果线程池数量不足,consumer无法创建.
2. 观察日志知道在启动jar实例时会打印日志,初始化
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor|Initializing ExecutorService 'applicationTaskExecutor'
3. 通过查看代码发现
@Lazy@Bean(name = {"applicationTaskExecutor"})@ConditionalOnMissingBean({Executor.class})public ThreadPoolTaskExecutor applicationTaskExecutor(TaskExecutorBuilder builder) {return builder.build();}
ThreadPoolTaskExecutor的bean对象'applicationTaskExecutor'是懒加载到spring中去的;
3.1 当我们消费者启动生成线程但applicationTaskExecutor未开始工作时,消费者线程池会使用SimpleAsyncTaskExecutor当消费者数量超过SimpleAsyncTaskExecutor限定值则不会创建后托管到spring中的消费者
3.2 当我们定义的applicationTaskExecutor的poolSize比较小,不能生产出足够多的线程则同样不能创建后托管到spring中的消费者
实践
在消费者定义中显式指定执行的线程池
线程池应有富裕的空间满足实例中的线程创建
附录
spring task executor 配置参数:
spring:task:execution:pool:allow-core-thread-timeout: true #是否允许回收空闲的线程,默认为truecore-size: 8 # 核心线程数,默认为8keep-alive: 60 #空闲的线程可以保留多少秒,默认为60。如果超过这个时间没有任务调度,则线程会被回收max-size: 2147483647 # 最大线程数,默认为2147483647queue-capacity: 2147483647 # 队列容量,默认为2147483647thread-name-prefix: task- # 线程名前缀,默认为thread-




