rabbitmq消息确认机制-confirm模式

本文介绍了RabbitMQ的Confirm消息确认机制,包括同步单条模式、同步多条模式和异步模式。在同步模式下,发送消息后会等待服务端确认;异步模式则通过监听回调方法来处理确认。示例代码展示了如何在Java中实现这些模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

同步:提交消息后,等待服务端回复后才算确认,概括的简单吧。

异步:使用监听方法,异步等待消息回调。

控制方式

开启confirm模式代码 : channel.confirmSelect();

同步确认,等待结果方法: channel.waitForConfirms() true-发送成功,false-发送失败

异步确认,直接添加一个监听,也能叫做监听模式:
channel.addConfirmListener(new ConfirmListener() {//实现返回处理方法... });

confirm 同步单条模式

提交一条后,直接调用等待回复方法

发送代码如下:

package com.yzcq.rabbitmq.confirm;

import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.yzcq.rabbitmq.util.ConnectionUtil; import java.io.IOException; import java.util.concurrent.TimeoutException;

/** 生产者-comfirm模式单条发送 **/

public class SendOne { private static final String QUEUE_NAME = "test-confirm_queue";

public static void main(String[] args) throws IOException, TimeoutException {
    //获取连接
    Connection connection = ConnectionUtil.getConnection();
    //创建通道
    Channel channel = connection.createChannel();

    //声明一个持久化的 队列
    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    //开启confirm模式
    channel.confirmSelect();

    String msg = "我是confirm模式消息";
    channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
    try {
        //          等待回复,如果回复true
        if (channel.waitForConfirms()) {
            System.out.println("发送成功");
        }
        else {
            System.out.println("发送失败");
        }
    }
    catch (InterruptedException e) {
        e.printStackTrace();
        System.out.println("发送失败");
    }
    channel.close();
    connection.close();

}

}

confirm 同步多条条模式

整批处理,成功、失败、回退都是整批的
提交多条后,调用等待回复方法

package com.yzcq.rabbitmq.confirm;

import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.yzcq.rabbitmq.util.ConnectionUtil; import java.io.IOException; import java.util.concurrent.TimeoutException;

/生产者-comfirm模式单条发送/

public class SendMore {

private static final String QUEUE_NAME = "SendMore-confirm_queue";

public static void main(String[] args) throws IOException, TimeoutException {

    //获取连接
    Connection connection = ConnectionUtil.getConnection();
    
    //创建通道
    Channel channel = connection.createChannel();
    //声明一个持久化的 队列
    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    //开启confirm模式
    channel.confirmSelect();
    String msg = "我是confirm模式 消息 批量发送";
    //多条一起发送
    for (int i = 0; i < 5; i++) {
        channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
    }
    try {

        //等待回复,如果回复true
        if (channel.waitForConfirms()) {
            System.out.println("发送成功");
        }
        else {
            System.out.println("发送失败");
        }
    }
    catch (InterruptedException e) {
        e.printStackTrace();
        System.out.println("发送失败");
    }
    channel.close();
    connection.close();
}

}

confirm 异步

package com.yzcq.rabbitmq.confirm;

import com.rabbitmq.client.Channel; import com.rabbitmq.client.ConfirmListener; import com.rabbitmq.client.Connection; import com.rabbitmq.client.MessageProperties; import com.yzcq.rabbitmq.util.ConnectionUtil; import java.io.IOException; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.TimeoutException;

/** 生产者-comfirm模式异步*/

public class SendAsync {

private static final String QUEUE_NAME = "SendAsync-confirm_queue";

public static void main(String[] args) throws IOException, TimeoutException {
    //获取连接
    Connection connection = ConnectionUtil.getConnection();
    //创建通道
    Channel channel = connection.createChannel();
    //声明一个持久化的 队列
    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    //开启confirm模式
    channel.confirmSelect();

    //存储未确认的消息标识tag
    final SortedSet<Long> confirmSet = Collections.synchronizedNavigableSet(new TreeSet<Long>());

    //开启监听
    channel.addConfirmListener(new ConfirmListener() {
        /**
         * 处理返回确认成功
         * @param deliveryTag 如果是多条,这个就是最后一条消息的tag
         * @param multiple 是否多条
         * @throws IOException
         */
        @Override
        public void handleAck(long deliveryTag, boolean multiple) throws IOException {

            System.out.println("消息发送成功,deliveryTag:" + deliveryTag + "multiple:" + multiple + "");
            if (multiple) {
                confirmSet.headSet(deliveryTag + 1).clear();
            }
            else {
                confirmSet.remove(deliveryTag);
            }
        }

        /**
         * 处理返回确认失败
         * @param deliveryTag
         * @param multiple
         * @throws IOException
         */
        @Override
        public void handleNack(long deliveryTag, boolean multiple) throws IOException {
            System.out.println("失败,deliveryTag:" + deliveryTag + "multiple:" + multiple + "");
            if (multiple) {

                confirmSet.headSet(deliveryTag + 1).clear();
            }
            else {
                confirmSet.remove(deliveryTag);
            }
        }
    });

    for (int i = 0; 1 < 2; i++) {
        String msg = "我是confirm模式 消息 异步【" + i + "】";
        long tag = channel.getNextPublishSeqNo();
        //发送消息
        channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());
        System.out.println("tag:" + tag);
        confirmSet.add(tag);
    }
    //上面是无限循环所以这个应该放到finally里
    //        channel.close();
    //        connection.close();
}

}

<think>我们正在使用Spring MVC整合RabbitMQ,并配置生产者确认机制(Publisher Confirms)。用户询问在XML配置中如何设置`publisher-confirm-type`。 根据引用[2]中的YAML配置示例,我们看到在YAML中配置了: ```yaml spring: rabbitmq: publisher-confirm-type: correlated ``` 但是,用户使用的是XML配置,并且是Spring MVC项目(非Spring Boot)。在传统的Spring XML配置中,我们需要通过`RabbitConnectionFactoryBean`或直接在连接工厂上设置相关属性来实现。 在Spring AMQP中,生产者确认机制(也称为发布者确认)是通过在连接工厂上设置`publisherConfirms`属性来启用的。在XML配置中,我们通常配置一个`ConnectionFactory` bean,然后设置其属性。 然而,需要注意的是,`publisher-confirm-type`是Spring Boot引入的配置项,用于更精细地控制确认类型(如`correlated`)。在非Spring Boot的Spring XML配置中,我们通常直接设置连接工厂的`publisherConfirms`和`publisherReturns`属性为`true`,然后通过`RabbitTemplate`的配置来支持关联的确认(correlated confirms)。 具体步骤: 1. 配置连接工厂,开启生产者确认和返回模式。 2. 配置RabbitTemplate,设置`confirm-callback`和`return-callback`(用于关联确认)。 在XML中,我们可以这样配置: ```xml <!-- 配置连接工厂 --> <rabbit:connection-factory id="connectionFactory" host="127.0.0.1" port="5672" username="guest" password="guest" publisher-confirms="true" <!-- 开启生产者确认 --> publisher-returns="true"/> <!-- 开启返回模式(当消息无法路由到队列时返回给生产者) --> <!-- 配置RabbitTemplate --> <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" confirm-callback="confirmCallback" <!-- 确认回调的Bean引用 --> return-callback="returnCallback" <!-- 返回回调的Bean引用 --> mandatory="true"/> <!-- 设置为true,当消息不可路由时才会触发return-callback --> ``` 这里,`publisher-confirms="true"`相当于Spring Boot中的`publisher-confirm-type=simple`或`correlated`的开启,但在非Boot环境中,我们通过设置这个属性为`true`来开启确认,并且通过`confirm-callback`和`return-callback`来实现关联确认。 注意:在非Boot的Spring XML配置中,没有直接名为`publisher-confirm-type`的属性,而是通过`publisher-confirms`和`publisher-returns`两个独立的属性来开启,然后通过回调接口实现关联。 回调接口的实现: 我们需要定义两个Bean,一个实现`RabbitTemplate.ConfirmCallback`接口,另一个实现`RabbitTemplate.ReturnCallback`接口。 例如: ```java public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { // 处理确认结果 } } public class RabbitReturnCallback implements RabbitTemplate.ReturnCallback { @Override public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) { // 处理返回的消息 } } ``` 然后在XML中声明这些Bean并注入到RabbitTemplate中: ```xml <bean id="confirmCallback" class="com.example.RabbitConfirmCallback"/> <bean id="returnCallback" class="com.example.RabbitReturnCallback"/> ``` 这样,当消息发送到Broker后,会异步调用这些回调方法。 总结: 在Spring MVC的XML配置中,没有直接名为`publisher-confirm-type`的配置项,而是通过: - 在连接工厂上设置`publisher-confirms="true"`来开启生产者确认。 - 在连接工厂上设置`publisher-returns="true"`来开启消息返回。 - 在RabbitTemplate上设置`confirm-callback`和`return-callback`属性来指定回调Bean,以实现关联确认。 因此,用户需要按照上述方式配置即可实现生产者确认机制。 相关问题: 1. 在Spring MVC中如何实现RabbitMQ生产者确认的同步等待? 2. RabbitMQ生产者确认机制中,`CorrelationData`的作用是什么? 3. 如何确保在消息发送失败时进行重试? 4. RabbitTemplate的`mandatory`属性有什么作用?</think>### Spring MVC 配置 RabbitMQ 生产者确认机制(XML 配置) 在 Spring MVC 中使用 XML 配置 RabbitMQ 的生产者确认机制,需要配置两个关键属性:`publisher-confirms` 和 `publisher-returns`。以下是完整配置步骤: #### 1. 配置连接工厂(启用确认机制) ```xml <rabbit:connection-factory id="connectionFactory" host="127.0.0.1" port="5672" username="guest" password="guest" publisher-confirms="true" <!-- 开启生产者确认 --> publisher-returns="true"/> <!-- 开启消息回退机制 --> ``` - `publisher-confirms="true"`:启用 Broker 确认机制(类似 `publisher-confirm-type` 功能) - `publisher-returns="true"`:启用消息无法路由时的回退机制 #### 2. 配置 RabbitTemplate(设置回调) ```xml <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" confirm-callback="confirmCallback" <!-- 确认回调Bean --> return-callback="returnCallback" <!-- 回退回调Bean --> mandatory="true"/> <!-- 强制消息路由检查 --> ``` #### 3. 实现回调接口(Java 代码) ```java public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { if(ack) { System.out.println("消息到达Broker: " + correlationData.getId()); } else { System.out.println("消息丢失: " + cause); } } } public class RabbitReturnCallback implements RabbitTemplate.ReturnCallback { @Override public void returnedMessage( Message message, int replyCode, String replyText, String exchange, String routingKey ) { System.out.println("消息无法路由: " + new String(message.getBody())); } } ``` #### 4. 注册回调 Bean(XML 配置) ```xml <bean id="confirmCallback" class="com.example.RabbitConfirmCallback"/> <bean id="returnCallback" class="com.example.RabbitReturnCallback"/> ``` #### 5. 完整配置示例 ```xml <!-- RabbitMQ 连接 --> <rabbit:connection-factory id="connectionFactory" host="127.0.0.1" publisher-confirms="true" publisher-returns="true"/> <!-- 模板配置 --> <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory" confirm-callback="confirmCallback" return-callback="returnCallback" mandatory="true"/> <!-- 回调实现 --> <bean id="confirmCallback" class="com.example.RabbitConfirmCallback"/> <bean id="returnCallback" class="com.example.RabbitReturnCallback"/> <!-- 队列声明 --> <rabbit:queue name="order.queue"/> <rabbit:direct-exchange name="order.exchange"> <rabbit:bindings> <rabbit:binding queue="order.queue" key="order.routing"/> </rabbit:bindings> </rabbit:direct-exchange> ``` ### 关键配置说明: 1. **publisher-confirms** 控制是否启用生产者确认(相当于 Spring Boot 中的 `publisher-confirm-type`),设置为 `true` 启用 2. **confirm-callback** 指定实现 `RabbitTemplate.ConfirmCallback` 接口的 Bean,处理以下情况: - `ack=true`:消息成功到达 Broker - `ack=false`:消息丢失(Broker 不可用或队列不存在) 3. **return-callback** 指定实现 `RabbitTemplate.ReturnCallback` 接口的 Bean,处理消息无法路由到队列的情况 4. **mandatory="true"** 强制检查消息路由,当消息无法路由时触发 return-callback(必须设置为 true) > **性能提示**:生产环境建议使用异步确认机制,同步确认会阻塞发送线程[^2] ### 工作流程: ```mermaid sequenceDiagram Producer->>Broker: 发送消息 Broker-->>Producer: 确认接收(ack/nack) alt 消息无法路由 Broker->>Producer: 触发returnCallback end ``` ### 测试验证 ```java // 发送消息时携带关联ID rabbitTemplate.convertAndSend("order.exchange", "order.routing", message, new CorrelationData(UUID.randomUUID().toString())); ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值