问题:rabbitmq 消费者自动中断连接:
发现生产上面mq 消费者无故就消失了,而且项目日志里面也没有看到mq相关异常发生,每当重启项目的时候有消费线程跑了秒中就中断了,不管mq消费线程一次拿多少个消息包,,每次一共消费了4000个消息包左右;后面排查日志的时候发现有oom异常,无法创建新的线程。这一下就发现了问题所在,紧接着查看到抛这个异常的线程名称对应的线程编号接近四千。由此排查自己代码:是由于processingToAclecounted 方法使用了 @Async 所以mq 的消费线程只管拿消息包,创建新的子线程任务再由于我们的项目的启动命令给定的堆内存空间只有2G 不断的创建线程任务很快就导致了OOM,,当内存超限了mq的消费线程也无法创建;
@RabbitListener(queues = MQConfigConst.OFFER_POINT_ACCOUNTING, concurrency = "5", containerFactory = MQConfigConst.InnerRabbitListenerCF)
public void pointAccountingToAccounted(Message message, Channel channel) {
log.debug("consume-messageId:{}", message.getMessageProperties().getMessageId());
String id = JSON.parseObject(new String(message.getBody(), StandardCharsets.UTF_8), String.class);
customPointService.processingToAccounted(id);
}
/**
* 处理入账中数据
* 入账成功、之前已经被入账、有入账明确结果 正常处理
* 网络问题 则抛出异常
*
* @param id 账目id
*/
@Override
@Async
public void processingToAclecounted(String id) {
log.debug("积分-入账-开始:{}", id);
String lockKey = String.format(RedisKeyUtil.OFFER_POINT_ACCOUNTED_LOCK.getKey(), id);
if (!redisUtils.setNX(lockKey, id, RedisKeyUtil.OFFER_POINT_ACCOUNTED_LOCK.getExpiredTime())) {
log.debug("积分-入账-失败-未获取到锁");
return;
}
}
spring 线程池默认配置
public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport implements AsyncListenableTaskExecutor, SchedulingTaskExecutor {
private final Object poolSizeMonitor = new Object();
private int corePoolSize = 1;
private int maxPoolSize = 2147483647;
private int keepAliveSeconds = 60;
private int queueCapacity = 2147483647;
private boolean allowCoreThreadTimeOut = false;
@Nullable
private TaskDecorator taskDecorator;
@Nullable
private ThreadPoolExecutor threadPoolExecutor;
private final Map decoratedTaskMap;
……
}
解决方案:
1、查看硬件内存剩余10G 所以将原有的堆空间2G 调大到8G ;
2、修改默认的线程内存至256K, 相固定的硬件内存可以开辟更多的线程;
3、 @Async 把这个注解去掉,mq 的多个消费线程已经满足业务需求了没有必要再开这么多线程去调第三方接口;