rabbitMq消息重复发送,重复ack原因

  • Post author:
  • Post category:其他




故事

这两天一直在做毕业设计,在搭建项目框架的时候遇到了rabbitMq相关的东西,然后之前自己有大致学习过,现在全部忘记的一干二净,然后就是基础不牢地动山摇,好好打基础吧



程序报错

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)

大概就是说,Channel这玩意已经关闭了,没了,为什么没了呢,开始我也一直想不明白,我明明在yml文件中配置了手动ack,yml像这样。

pring:
  rabbitmq:
    addresses: xxx.xxx.xxx.xxx:xxxx
    username: admin
    password: admin
    publisher-confirms: true
    publisher-returns: true
    #默认虚拟主机
    virtual-host: /
    #连接超时实践
    connection-timeout: 10000
    publisher-confirm-type: correlated
    template:
      mandatory: true
      retry:
        max-attempts: 5 #最大重试次数
        max-interval: 10000 #最大重试时间
    #消费端配置
    listener:
      type: direct
      direct:
        max-concurrency: 50
        concurrency: 10
        acknowledge-mode: manual #签收设置
        retry:
          enabled: true
          initial-interval: 50000
        prefetch: 1 #限流

然后百度了很多,emmmm全是复制粘贴,关键是还解决不了我的问题。造成这个错误会有啥结果呢?



错误结果

生产者所投递的消息,虽然只是投递了一次,但是

消费者会进行两次或者多次应答,然后造成消息被被两次以上重复投递



错误原因

进行多次ack,重复ack所造成



出现原因

应为在rabbitmqConf中使用了序列化设置,造成了设置manual失效。原来的配置类如下:


出现错误的配置类

@Configuration
public class RabbitMqConfig implements RabbitListenerConfigurer {

    ...
  
	...

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar rabbitListenerEndpointRegistrar) {
        rabbitListenerEndpointRegistrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
    }

    @Bean
    MessageHandlerMethodFactory messageHandlerMethodFactory(){
        DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
        messageHandlerMethodFactory.setMessageConverter(mappingJackson2MessageConverter());
        return messageHandlerMethodFactory;
    }

    @Bean
    public MappingJackson2MessageConverter mappingJackson2MessageConverter(){
        return  new MappingJackson2MessageConverter();



处理

在配置类的SimpleRabbitListenerContainerFactory中增加

 factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);

到此问题得以解决。修改后的配置文件为


/**
 * @author WangShilei
 * @date 2020/11/13-13:34
 **/
@Configuration
@Slf4j
public class RabbitMqConfig {

   ...
	...

    @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.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);
        return factory;
    }

    @Bean
    public MessageConverter messageConverter() {
        return new ContentTypeDelegatingMessageConverter(new Jackson2JsonMessageConverter());
    }
}



版权声明:本文为qq_40432886原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。