问题背景
目前LEX业务场景包含两个模块:FM、LineHaulShuttle,都是通过ODPS离线同步然后通过Blink发送到gateway的MQ,两个QPS分别是:FM-1000/s,LineHaulShuttle-600/s,会对系统有个短暂的冲击,目前系统未经过压测,所以对于系统的抗压能力我们是不清楚的,如下就是接入LinHaul场景时发现的异常:线程池占满
问题排查
由于Lindorm入库、发风控是使用了线程池异步操作的,这样不仅能提高系统处理效率还能提高吞吐量,但是由于线程资源有限,所以就会发生如上的异常,查看代码:
可以发现两个问题:
- 当前线程缓冲队列大小为:200,当QPS超过200甚至更多的时候,就会触发创建最大线程
- 当前线程池使用的策略是:AbortPolicy,这将导致达到最大线程数时,新任务将直接被丢弃
@EnableAsync
@Configuration
public class AsyncThreadPoolConfig {
/**
* 核心线程数(默认线程数)
*/
private static final int CORE_POOL_SIZE = 8;
/**
* 最大线程数
*/
private static final int MAX_POOL_SIZE = 20;
/**
* 允许线程空闲时间(单位:默认为秒)
*/
private static final int KEEP_ALIVE_TIME = 10;
/**
* 缓冲队列大小
*/
private static final int QUEUE_CAPACITY = 200;
/**
* 线程池名前缀
*/
private static final String THREAD_NAME_PREFIX = "async-task-pool-";
/**
* 当使用@Async注解时,需指定使用此线程池
* @return 线程池实例
*/
@Bean("asyncTaskExecutor")
public ThreadPoolTaskExecutor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.setThreadFactory(new ThreadFactory() {
// 线程计数器
private final AtomicInteger threadNumber = new AtomicInteger(0);
@Override
public Thread newThread(@NotNull Runnable runnable) {
Thread thread = new