rabbitMQ消息队列中发布确认中的确认以及回退回调的实现

本文详细介绍了在rabbitMQ中如何实现发布确认回调和消息不可路由时的回退回调,以防止消息丢失。重点在于理解如何在发布确认回调实现类中设置ConfirmCallBack,确保即使遇到服务器宕机或队列问题也能正常执行确认。此外,还讨论了消息不可路由的两种解决方案:一是通过回退回调,当路由key未找到时将消息退回;二是设置备份交换机,当消息无法路由时,备份交换机会接管处理。配置文件的相应设置也是关键部分。

在发布确认回调实现类中

package com.it.springbootrabbitmq.callback;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Slf4j
@Component
//发布确认回调实现类
public class MyCallBack  implements RabbitTemplate.ConfirmCallback {

    @Autowired
    private  RabbitTemplate rabbitTemplate;
    //由于confirm回调函数是在rabbitTemplate类中进行调用的, 调用方法为handleConfirm .只有属性ConfirmCallBack
    //	if (this.confirmCallback != null) {
    //		this.confirmCallback
    //		.confirm(pendingConfirm.getCorrelationData(), ack, pendingConfirm.getCause()); // NOSON
    //不为null  才会被调用 因此, 需要首先在类注入后, 进行初始化,为回调实现类进行赋值,进而每次发出消息都会激发回调函数
    //且 PostConstruct  注解是专门数据初始化的注解, 只有其他组件注入后,初始化方法才会执行,
    @PostConstruct
    public void  init(){
        rabbitTemplate.setConfirmCallback(this);
    }

    //交换机确认回调方法
    /*
    * correlationData   保存回调消息的ID及相关信息
    * ack   表示交换机是否收到消息
    * cause   失败的原因, 成功为null
    * */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
      String  id= correlationData!=null?correlationData.getId() : "";
      if (ack){
          log.info("交换机已经收到了ID为:{}的消息", id);
      }else {
          log.info("交换机还未收到ID为:{}的消息,由于原因:{}", id,cause );
      }

    }
}

难理解的地方:
在这里插入图片描述

这里首先需要注入rabbitTemplate操作工具类,这是依赖为我们提供好的, 而我们虽然实现了实现类, 但由于实现的是rabbitTemplate类的内部接口,在其类中声明了ConfirmCallBack属性, 我查看源码注意到一个方法
在这里插入图片描述
这个方法 很清楚的key看到 ,只有在confirCallback确认回调不为null 时才会执行其中的回调实现类调用确认confirm方法的逻辑, 因此, 我们在数据初始化的时候, 必须在给rabbittemplate中注入confirmCallback值, 进行数据的初始化, 这样在消费者发送消息后,不管中间出现了什么问题:rabbbit服务器宕机,队列挂掉,等等, 都是正常执行确认回调函数, 确认ack位true 未确认为false , 这样就解决了 rabbbit服务器宕机,队列挂掉等原因造成的消息丢失的故障问题

消息不可路由的解决方式一: 回退回调

  //可以在当消息传递过程中不可达目的地时将消息返回给生产者
    //只有不可达目的地的时候  才进行回退

    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.info("消息{},被交换机:{}退回,原因是:{},路由key是:{}",
                new String(returned.getMessage().getBody()), returned.getExchange(), returned.getReplyText(), returned.getRoutingKey());

    }

因为只设置发布交换机确认回调的话,只能解决交换机宕机的问题, 而在 队列,未收到消息, 也就是路由key no found 的情况下, 交换机还会>
正常确认, 因为其已收到消息, 但我们需要知道队列是否 收到, 如果没有收到的话, 能够将消息给发送者退回, 进行其他处理
因此, 我们需要实现回退, 同样实现回退接口, 然后实现方法
同样的, 回退回调实现类也需要注入到rabbitTemplate类中, 才会进行调用

完整发布确认代码如下

package com.it.springbootrabbitmq.callback;

import com.rabbitmq.client.ReturnCallback;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Slf4j
@Component
//发布确认回调实现类
public class MyCallBack  implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //由于confirm回调函数是在rabbitTemplate类中进行调用的, 调用方法为handleConfirm .只有属性ConfirmCallBack
    //	if (this.confirmCallback != null) {
    //		this.confirmCallback
    //		.confirm(pendingConfirm.getCorrelationData(), ack, pendingConfirm.getCause()); // NOSON
    //不为null  才会被调用 因此, 需要首先在类注入后, 进行初始化,为回调实现类进行赋值,进而每次发出消息都会激发回调函数
    //且 PostConstruct  注解是专门数据初始化的注解, 只有其他组件注入后,初始化方法才会执行,
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }


    //交换机确认回调方法
    /*
     * correlationData   保存回调消息的ID及相关信息
     * ack   表示交换机是否收到消息
     * cause   失败的原因, 成功为null
     * */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData != null ? correlationData.getId() : "";
        if (ack) {
            log.info("交换机已经收到了ID为:{}的消息", id);
        } else {
            log.info("交换机还未收到ID为:{}的消息,由于原因:{}", id, cause);
        }

    }
    //可以在当消息传递过程中不可达目的地时将消息返回给生产者
    //只有不可达目的地的时候  才进行回退

    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.info("消息{},被交换机:{}退回,原因是:{},路由key是:{}",
                new String(returned.getMessage().getBody()), returned.getExchange(), returned.getReplyText(), returned.getRoutingKey());

    }
}

配置文件需要进行如下配置:

#开启交换机发布确认模式,交换机收到或者未收到消息, 都会调用回调实现类的回调确认方法
spring.rabbitmq.publisher-confirm-type=correlated
#开启回退消息 , 当交换机无法将消息路由出去, 便会将消息回退给生产者
spring.rabbitmq.publisher-returns=true

消息不可路由的解决方式二:设置备份交换机

通过设置备份交换机进行解决消息不可路由 在确认交换机中, 设置备份交换机参数, 这样当消息不可路由的时候,确认交换机便会将
消息传递给备份交换机进行处理 而且 由于回退实现类也就是mandatory参数与备份交换机一起使用的时候, 如果两者同时开始, 备份交换机优先级要搞

 //声明确认交换机
    @Bean
    public DirectExchange  confirmExchange(){

        return  ExchangeBuilder.directExchange(CONFIRM_EXCHANGE_NAME)
       //这里是alternate 是将确认交换机与备份交换机建立关系, 一旦发现不可路由消息,便会将消息传递给备份交换机处理
                .alternate(BACKUP_EXCHANGE_NAME).build();
    }
<think>好的,我现在需要帮用户解决在Spring Boot中集成RabbitMQ实现消息发送确认(ACK)机制的问题。首先,我得回忆一下用户提供的参考内容,里面有三个引用,都是关于Spring Boot整合RabbitMQ的消息确认机制,特别是生产者发送确认的部分。用户需要的是示例教程,所以应该给出具体的步骤和代码示例。 首先,我应该确认消息确认机制的基本概念。RabbitMQ的消息确认分为生产者的确认和消费者的确认。这里用户关注的是发送方的确认,也就是生产者如何知道消息是否成功到达Broker。根据引用中的内容,生产者确认有两种方式:事务机制和确认模式,而确认模式更高效,所以应该使用ConfirmCallback和ReturnsCallback。 接下来,我需要整理实现步骤。根据引用3,配置RabbitTemplate,并实现ConfirmCallback和ReturnsCallback。步骤可能包括添加依赖、配置application.yml、定义交换机和队列、配置生产者确认机制、发送消息以及测试验证。 然后,我需要考虑代码示例的具体内容。比如,在Spring Boot项目中,如何配置RabbitTemplate的确认回调和退回回调。可能需要在配置类中设置相关参数,并实现对应的接口。同时,要处理消息成功到达Exchange的情况,以及消息无法路由到队列的情况,这时需要记录日志或者进行其他处理。 还要注意,用户可能需要知道如何开启生产者确认模式,这在配置文件中需要设置publisher-confirm-type和publisher-returns。另外,消息的mandatory属性需要设置为true,以确保无法路由的消息能触发退回机制。 另外,需要确保用户了解每个步骤的作用。例如,配置ConfirmCallback是为了处理消息到Exchange的确认,而ReturnsCallback处理消息无法路由到队列的情况。同时,发送消息时需要设置correlationData,以便在回调中关联消息和确认结果。 最后,检查是否有遗漏的部分,比如依赖的添加是否正确,是否需要定义交换机和队列的Bean,以及如何测试整个机制是否生效。可能还需要提醒用户注意版本兼容性,比如Spring Boot和RabbitMQ的版本是否匹配,但用户没有提到具体版本,所以可能暂时不需要涉及。 总结下来,回答的结构应该是先介绍机制,然后分步骤说明如何配置和实现,给出代码示例,最后提供相关问题和测试方法。确保所有内容符合用户的要求,使用中文,代码正确,并正确引用提供的参考资料。</think>在Spring Boot中集成RabbitMQ实现消息发送确认(ACK)机制,可通过以下步骤完成: --- ### 一、消息确认机制原理 RabbitMQ生产者确认包含两种类型: - **ConfirmCallback**:确认消息是否到达Exchange - **ReturnsCallback**:确认消息是否从Exchange路由到Queue[^3] 当消息无法被路由时,会触发消息回退机制[^2]。 --- ### 二、具体实现步骤 #### 1. 添加依赖 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` #### 2. 配置文件`application.yml` ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest publisher-confirm-type: correlated # 开启确认模式 publisher-returns: true # 开启回退模式 template: mandatory: true # 强制消息必须路由到队列 ``` #### 3. 定义交换机与队列 ```java @Configuration public class RabbitConfig { @Bean public DirectExchange directExchange() { return new DirectExchange("test.exchange"); } @Bean public Queue testQueue() { return new Queue("test.queue"); } @Bean public Binding binding() { return BindingBuilder.bind(testQueue()).to(directExchange()).with("test.routingKey"); } } ``` #### 4. 配置生产者确认机制 ```java @Slf4j @Component public class RabbitConfirmConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback { @Autowired public void setupRabbitTemplate(RabbitTemplate rabbitTemplate) { rabbitTemplate.setConfirmCallback(this); // 设置确认回调 rabbitTemplate.setReturnsCallback(this); // 设置回退回调 } /** * 消息到达Exchange的回调 */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { if (ack) { log.info("消息成功到达交换机,ID: {}", correlationData.getId()); } else { log.error("消息未到达交换机,原因: {}", cause); } } /** * 消息路由失败的回调 */ @Override public void returnedMessage(ReturnedMessage returned) { log.error("消息路由失败:{} -> 交换机:{} -> 路由键:{}", returned.getMessage(), returned.getExchange(), returned.getRoutingKey()); } } ``` #### 5. 发送消息 ```java @Service public class MessageSender { @Autowired private RabbitTemplate rabbitTemplate; public void sendMessage(String message) { CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString()); rabbitTemplate.convertAndSend( "test.exchange", "test.routingKey", message, correlationData ); } } ``` --- ### 三、测试验证 1. **成功场景**:消息正常路由时,`ConfirmCallback`会收到`ack=true` 2. **失败场景**: - 发送到不存在的Exchange:`ack=false` - 路由键错误:触发`ReturnsCallback` --- ### 四、关键配置说明 | 配置项 | 作用 | |---------------------------|--------------------------------------------------------------------| | publisher-confirm-type | 设置确认模式(CORRELATED表示关联确认)[^1] | | publisher-returns | 启用消息回退机制 | | mandatory=true | 强制要求消息必须被路由到队列,否则触发回退[^3] | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值