operation basic.ack caused a channel exception precondition_failed: unknown delivery tag 1

文章描述了一个在使用RabbitMQ时遇到的问题,即在手动确认消息消费时,日志中出现unknowndeliverytag错误。通过检查配置发现,由于`SimpleRabbitListenerContainerFactory`默认设置为自动签收,导致手动确认模式失效。解决方法是更改配置为手动acknowledge模式。
摘要由CSDN通过智能技术生成

问题

rabbitmq消费手动确认时rabbitmq日志报 unknown delivery tag 1,代码日志报
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)
在这里插入图片描述
在这里插入图片描述

代码

@Configuration
@Slf4j
public class RabbitConfig {
    // 定义死信队列
    @Bean
    public Queue deadLetterQueue() {
        return new Queue("deadLetterQueue");
    }

    @Bean
    public DirectExchange deadLetterExchange() {
        return new DirectExchange("deadLetterExchange");
    }
    // 绑定死信队列和死信交换机
    @Bean
    public Binding deadLetterBinding() {
        return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()).with("deadLetterKey");
    }

    @Bean
    public Queue illegalAlarmQueue() {
        return QueueBuilder.durable("illegalAlarmQueue")
                .withArgument("x-dead-letter-exchange", "deadLetterExchange")
                .withArgument("x-dead-letter-routing-key", "deadLetterKey")
                .build();
    }

    @Bean
    public DirectExchange masterExchange() {
        return new DirectExchange("masterExchange");
    }

    @Bean
    public Binding illegalAlarmBinding() {
        return BindingBuilder.bind(illegalAlarmQueue()).to(masterExchange()).with("illegalAlarmKey");
    }
    
    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }
}

 @RabbitListener(queues = "illegalAlarmQueue")
    public void receiveMessageIllegalAlarmQueue(Message message, Channel channel) throws IOException {
        IllegalAlarm illegalAlarm = (IllegalAlarm) jsonMessageConverter.fromMessage(message);
        try {
            List<String> paths = new ArrayList<>(6);
            paths.add(illegalAlarm.getTempPicturePath1());
            paths.add(illegalAlarm.getTempPicturePath2());
            paths.add(illegalAlarm.getTempPicturePath3());
            if (channel.isOpen()) {
                List<File> fileEntities = createFileEntities(paths);
                //手动提交事务
                Boolean result = transactionTemplate.execute(status -> {
                    try {
                        IllegalAlarm illegalAlarmTemp = illegalAlarmServiceI.saveIllegalAlarm(illegalAlarm);
                        int res = fileServiceI.saveBatch(fileEntities);
                        if (illegalAlarmTemp != null && res > 0) {
                            log.info("保存完成,id:{}",illegalAlarmTemp.getId());
                            return true;
                        }
                        return false;
                    } catch (Exception e) {
                        log.error("保存记录出现错误,异常信息:{}", e.getMessage());
                        // 回滚事务
                        status.setRollbackOnly();
                        return false;
                    }
                });
                if(result){
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                }
            }
        } catch (Exception e) {
            log.error("{}消费消息错误,异常信息:{}", illegalAlarm.getId(), e.getMessage());
            log.error("详情:{}", JSON.toJSONString(illegalAlarm));
            if (channel.isOpen()) {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            }
        }
    }
spring: 
  rabbitmq:
    host: 192.168.5.100
    port: 5672
    username: guest
    password: guest

以上是我的配置文件。

原因

原因是因为进行了两次消息确认double ack.,配置手动签收模式失效,被注解注入的SimpleRabbitListenerContainerFactory覆盖,而它默认使用了自动签收。

解决

在这里插入图片描述
在这里插入图片描述

配置类

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
        return factory;
    }
 spring:
  rabbitmq:
    host: 192.168.5.188
    port: 5672
    username: guest
    password: guest
    listener:
      direct:
        acknowledge-mode: manual # 消费端手动ack消息

参考

rabbitmq reply-text=PRECONDITION_FAILED

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值