记一次 springBoot + rabbitMQ设置手动ACK时的异常,配置文件设置了
//表示启动消费方的手动确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
但手动ACK没有生效,代码接收消息后,当业务完毕,执行:
//确认消息已经被消费
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
异常为:
2018-11-05 17:33:33.090 [ERROR] [AMQP Connection 59.110.229.19:5672] Caller+0 at org.springframework.amqp.rabbit.connection.CachingConnectionFactory$DefaultChannelCloseLogger.log(CachingConnectionFactory.java:1199)
Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
2018-11-05 17:33:34.081 [WARN ] [SimpleAsyncTaskExecutor-2] Caller+0 at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.logConsumerException(SimpleMessageListenerContainer.java:1462)
Consumer raised exception, processing can restart if the connection factory supports it
com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:484)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:321)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:560)
at java.lang.Thread.run(Thread.java:748)
2018-11-05 17:33:34.082 [INFO ] [SimpleAsyncTaskExecutor-2] Caller+0 at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1453)
Restarting Consumer: tags=[{amq.ctag-zms15dchTPRiv8SH2W0_8Q=videoChange}], channel=Cached Rabbit Channel: AMQChannel(amqp://admin@59.110.229.19:5672/,2), conn: Proxy@131c5bd Shared Rabbit Connection: SimpleConnection@3a500321 [delegate=amqp://admin@59.110.229.19:5672/, localPort= 50032], acknowledgeMode=AUTO local queue size=0
体现重点的有两条:
1、com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - unknown delivery tag 1, class-id=60, method-id=80)
表明这条消息对于MQ来说没找到,重点是这个---unknown delivery tag 1-参考rabbitMQ的tag机制可知这条消息已经完成了消费。
2、Restarting Consumer: tags=[{amq.ctag-zms15dchTPRiv8SH2W0_8Q=videoChange}], channel=Cached Rabbit Channel: AMQChannel(amqp://admin@59.110.229.19:5672/,2), conn: Proxy@131c5bd Shared Rabbit Connection: SimpleConnection@3a500321 [delegate=amqp://admin@59.110.229.19:5672/, localPort= 50032], acknowledgeMode=AUTO local queue size=0
表明这条消息被一个设置为自动确认的任务(至于他具体是啥,怎么执行的,没深入看源码,等大神给解释了。)给确认了。
各种百度,发现MQ配置的时候,如果配置了json解析器。如下:
@Bean
public MessageConverter messageConverter() {
return new ContentTypeDelegatingMessageConverter(new Jackson2JsonMessageConverter());
}
则程序会走自动确认消费,配置文件的配置就不生效了(这个不知道为什么,也可能springboot中某些配置的先后顺序的问题)
这个问题解决办法就是重写一下这个东东,用代码设置手动确认。就OK了
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory(
ConnectionFactory connectionFactory){
SimpleRabbitListenerContainerFactory factory =
new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(new Jackson2JsonMessageConverter());
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return factory;
}
本文由 创作,采用 知识共享署名4.0 国际许可协议进行许可。本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为: 2020/05/17 03:07