记一次 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
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
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://[email protected]:5672/,2), conn: Proxy@131c5bd Shared Rabbit Connection: SimpleConnection@3a500321 [delegate=amqp://[email protected]:5672/, localPort= 50032], acknowledgeMode=AUTO local queue size=0
体现重点的有两条:
1、com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method
表明这条消息对于MQ来说没找到,重点是这个---unknown delivery tag 1-参考rabbitMQ的tag机制可知这条消息已经完成了消费。
2、Restarting Consumer: tags=[{amq.ctag-zms15dchTPRiv8SH2W0_8Q=videoChange}], channel=Cached Rabbit Channel: AMQChannel(amqp://[email protected]:5672/,2), conn: Proxy@131c5bd Shared Rabbit Connection: SimpleConnection@3a500321 [delegate=amqp://[email protected]: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; }