记一次 SpringBoot-Rabbit MQ设置手动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.CachingConnectionFactoryKaTeX parse error: Expected 'EOF', got '#' at position 117: …otocol method: #̲method<channel.…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
M
a
i
n
L
o
o
p
.
r
u
n
(
A
M
Q
C
o
n
n
e
c
t
i
o
n
.
j
a
v
a
:
560
)
a
t
j
a
v
a
.
l
a
n
g
.
T
h
r
e
a
d
.
r
u
n
(
T
h
r
e
a
d
.
j
a
v
a
:
748
)
2018
−
11
−
0517
:
33
:
34.082
[
I
N
F
O
]
[
S
i
m
p
l
e
A
s
y
n
c
T
a
s
k
E
x
e
c
u
t
o
r
−
2
]
C
a
l
l
e
r
+
0
a
t
o
r
g
.
s
p
r
i
n
g
f
r
a
m
e
w
o
r
k
.
a
m
q
p
.
r
a
b
b
i
t
.
l
i
s
t
e
n
e
r
.
S
i
m
p
l
e
M
e
s
s
a
g
e
L
i
s
t
e
n
e
r
C
o
n
t
a
i
n
e
r
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
MainLoop.run(AMQConnection.java:560)atjava.lang.Thread.run(Thread.java:748)2018−11−0517:33:34.082[INFO][SimpleAsyncTaskExecutor−2]Caller+0atorg.springframework.amqp.rabbit.listener.SimpleMessageListenerContainerAsyncMessageProcessingConsumer.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;
}
转载:https://blog.youkuaiyun.com/m912595719/article/details/83787486