Listener method 'public void com.config.mq.MsgReceiver.process(java.lang.String) throw
RabbitMQ监听消息时遇到的错误,项目启动就会持续跳出来,其实仔细可以明白其意思,就是有一个公有化的监听方法参数是String类型,所以抛出异常;
开始的时候这样是不会报错的,因为RabbitMQ中队列接受的就是String类型,如果中途因为某种原因,修改了参数的类型,这时参数的类型应该是Message类型,再次切换回String类型或其他类型,就会导致参数类型不匹配,消息无法消费,这是消息的类型会一直保持Message类型,它的类型是向下兼容改变方式;
- 解决这样的问题我有两种方式:
1.简单粗暴,直接打开RabbitMQ服务,找到对应的坐标(交换机、路由器、队列)直接删除,让其重新生成;
2.使用Message(org.springframework.amqp.core.Message),getBody()将参数取出转换成所需要的类型即可;
经过线上多次测试,由于消息生成者和消费者已经配置好了,短时间内上面的两种方式可以解决问题,长时间后还是会出现消费不掉的消息,最后解决采用以下方式:
- 开启线程,参数类型继续为String类型
线程池配置(SpringBoot)
/**
* 线程池配置 by CHENYB date 2019-07-29
*/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Bean
@Override
public Executor getAsyncExecutor() {
//线程池设置
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize( 8 );//核心线程
taskExecutor.setMaxPoolSize( 16 );//最大线程
taskExecutor.setQueueCapacity( 64 );//队列大小
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setThreadNamePrefix( "async-token-" );
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SpringAsyncExceptionHandler();
}
class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
//logger.error("Exception occurs in async method", throwable.getMessage());
}
}
}
消费者配置:
其中@Component注解,一定不可以是@Service,会导致消息一旦监听失败,不会重复发起请求,会报错线程问题
在SpringBoot中@Async开启异步
package com.wenjie.consumer.listener;
import com.alibaba.fastjson.JSON;
import com.wenjie.common.entity.TransactionRecord;
import com.wenjie.consumer.feign.RecordFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Date;
@Slf4j
@Component
public class TopicConsumerListener {
@Autowired
private RecordFeignService recordFeignService;
@RabbitListener(queues = "transfer_Queue")
@Async
public void receiveTransfer(@Payload String s) throws IOException {
TransactionRecord transactionRecord = JSON.parseObject(s,TransactionRecord.class);
recordFeignService.addRecord(transactionRecord);
System.out.println(s);
log.info("当前时间:{},收到队列信息{}", new Date().toString(), s);
}
}
当初就是用的@Service注解,导致线程报错产生,后想去掉线程回归原始,接受消息时采用Message类型,最后标题错误出现,解决本次问题采用的最后的解决方案,即开启了异步消费消息,又解决了消费参数类型不匹配问题,还是有点懵,但是问题解决了