报错信息:
16:50:10.134 ERROR 17788 --- o.s.a.r.c.CachingConnectionFactory :
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)
使用rabbitmq的时候总是报错信道关闭。网上查了原因,大多说的是因为没有配置RabbitAdmin,无法自动创建exchange的。但是我配置了RabbitAdmin,也能够自动创建exchange,还是报这个错,而且这个错居然不影响消息队列运行。
后来看到这篇文章https://www.cnblogs.com/zhjh256/p/6434093.html,其中提到double ack问题,联想到我配置了序列化为json格式,所以重新配置了rabbitmq,
@Configuration
public class RabbitMqConfig {
@Bean
public RabbitAdmin rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(messageConverter);
return template;
}
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(messageConverter);
return factory;
}
@Bean
public MessageConverter messageConverter() {
return new ContentTypeDelegatingMessageConverter(new Jackson2JsonMessageConverter());
}
}
在yml配置文件中设置了手动ack
spring:
rabbitmq:
host: localhost
port: 5672
username: rabbit
password: 123456
virtual-host: /
#生产端
publisher-confirms: true
publisher-returns: true
template:
mandatory: true
#消费端
listener:
simple:
acknowledge-mode: manual
#初始连接数量
concurrency: 5
#最大连接数量
max-concurrency: 10
#限流
prefetch: 1
yml中的签收模式失效,被注解注入的SimpleRabbitListenerContainerFactory覆盖,而它默认使用了自动签收。但是消费消息的时候又手动进行channel.basicAck(deliveryTag, false),于是导致了两次ack,所以报错。
解决方法是在rabbitmq的factory中指定ack模式。
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
factory.setConnectionFactory(connectionFactory);
factory.setMessageConverter(messageConverter);
return factory;
}
```