1、 问题描述
使用MQ队列机制,实现异步消费消息,使用一段时间后,发现消息不能及时消费,每隔5分钟可以执行,查看MQ后台,发现Unacked的消息积累了非常多,导致后续进来的消息无法消费。
2、分析
想到elasticjob中有个5分钟的任务,怀疑影响到了MQ的消费,就把job停掉,但仍不生效,不是job引起的。
启动本地环境,消费MQ的消息,Unacked消息急剧下降,但很快就又上升上去了。下一步仔细检查MQ的配置,发现了问题所在:
spring.rabbitmq.listener.simple.acknowledge-mode=manual
mq被配置成了手动应答方式,删掉这个配置(或修改成自动),重启服务,Unacked的消息立刻被消费,后续Q正常消费,问题解决。
3、回顾
springBoot的项目中,如果没有指定rabbitMQ的应答方式,默认是自动应答,如果设置为manual方式,必须手动应答:
Long deliverTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
channel.basicAck(deliverTag, false);
当然可以利用手动应答机制,完善mq的消费成功率,如果业务发生异常,再把消息吐回消息队列,供其他消费者消费。
所以就出现了启动本地环境,MQ的Unacked消息急剧下降,被本地消费者消费掉,后来Unacked消息又上升,则是因为本地的应答方式也是手动。
另外RabbitMQ 5分钟执行,可能跟RabbitMQ的某个机制有关,有待研究