rabbitMq的确认机制

136 阅读3分钟

RabbitMQ的消息确认有两种 一种是消息发送确认。这种是用来确认生产者将消息发送给交换器,交换器传递给队列的过程中,消息是否成功投递。发送确认分为两步,一是确认是否到达交换器,二是确认是否到达队列。

第二种是消费接收确认。这种是确认消费者是否成功消费了队列中的消息。

实现当前接口的配置类,当消息向消息队列发送消息时 会自动触发相关回调方法
import org.springframework.amqp.core.Message;
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;

/**
 * @author atguigu-mqx
 */
@Component
public class MQProducerAckConfig implements RabbitTemplate.ReturnCallback, RabbitTemplate.ConfirmCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //  编写一个初始化方法!
    @PostConstruct
    public void init(){
        rabbitTemplate.setReturnCallback(this);
        rabbitTemplate.setConfirmCallback(this);
    }

    /**
     * 表示判断消息是否发送到交换机!
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        //  判断
        if (ack){
            System.out.println("发送成功....");
        }else {
            System.out.println("发送失败....");
        }
    }

    /**
     * 判断当前消息是否能够到队列中! 如果到队列中了,则这个方法不执行! 如果没有到队列中,则方法执行!
     * @param message
     * @param replyCode
     * @param replyText
     * @param exchange
     * @param routingKey
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
//        可以通过判断方式来确切指定哪些是基于延迟插件的交换机路由键 ! 则 return!
//        if ("exchange.delay".equals(exchange) && "routing.delay".equals(routingKey)){
//            return;
//        }

        System.out.println("消息主体: " + new String(message.getBody()));
        System.out.println("应答码: " + replyCode);
        System.out.println("描述:" + replyText);
        System.out.println("消息使用的交换器 exchange : " + exchange);
        System.out.println("消息使用的路由键 routing : " + routingKey);
    }
}
定义发送消息的方法
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author atguigu-mqx
 */
@Service
public class RabbitService {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    //  编写发送消息的方法
    public Boolean sendMessage(String exchange, String routingKey, Object message){
        //  发送消息
        this.rabbitTemplate.convertAndSend(exchange,routingKey,message);
        //  返回值
        return true;
    }
生产者 向消息队列发送消息
//想要往交换机发送消息 只需要调用发送消息的方法 往交换机发送消息就可以了
//发送消息的三个参数需要跟消息监听器中的 交换机 消息队列的名称 和 路由Key对应上
消费者 监听消息队列 并确认消息
//  监听消息:
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
        //=======参数1:消息队列名称 参数2:是否过期 参数3:不自动删除
        value = @Queue(value = "消息队列名称,一般是从定义的常量类中取出",durable = "true",autoDelete = "false"),
        //=========参数:交换机名称,当前名称是从常量类中取出
        exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY),
        //========交换机连接消息队列的 路由key,这里直接从常量类中取的数据
        key = {MqConst.ROUTING_PAYMENT_PAY}
))
public void updateOrderStatus(Long orderId,Message message,Channel channel){
   /**
       这里写业务逻辑代码
   */
   
    //  一定要确认消息,被消费掉!当前方法可以批量拒绝多条消息
    //basicNack(long deliveryTag, boolean multiple, boolean requeue)
    //deliveryTag:该消息的index。multiple:是否批量. true:将一次性拒绝所有小于deliveryTag的消息。requeue:被拒绝的是否重新入队列。
    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
}
最后一定要记得 创建交换机和相关消息队列还有设置交换机和消息队列直接的路由Key
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

/**
 * @author atguigu-mqx
 注意:这个类中只是演示了 交换机和消息队列的初始化 
 即:一个交换机绑定一个消息队列 
 */
@Configuration
public class DelayedMqConfig {

    //  一个交换机一个队列一个绑定关系!
    public static final String exchange_delay = "exchange.delay";
    public static final String routing_delay = "routing.delay";
    public static final String queue_delay_1 = "queue.delay.1";

    //  定义交换机
    @Bean
    public CustomExchange delayExchange(){
        //  设置参数
        HashMap<String, Object> map = new HashMap<>();
        //设置交换机的类型
        map.put("x-delayed-type","direct");
        //  第二个参数固定值!
        return new CustomExchange(exchange_delay,"x-delayed-message",true,false,map);
    }
    //  定义队列
    @Bean
    public Queue delayQueue(){
        //  返回队列  设置消息队列名称,消息不过期,消息不自动删除等参数
        return new Queue(queue_delay_1,true,false,false);
    }
    //  定义绑定关系 定义交换机和消息队列是用哪个 路由Key连接的
    @Bean
    public Binding delayBinding(){
        //  返回绑定关系!
        return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(routing_delay).noargs();
    }
}