rabbitmq学习7-springboot和rabbitmq发送方确认及手动确认

正常情况下,如果消息经过交换器进入队列就可以完成消息的持久化,但如果消息在没有到达broker之前出现意外,那就造成消息丢失,有没有办法可以解决这个问题?

RabbitMQ有两种方式来解决这个问题:

一、通过AMQP提供的事务机制实现;

二、使用发送者确认模式实现

如下为使用发送发确认来保证队列到达队列

1、开启发送发确认,及开启消息手动确认

rabbitmq学习7-springboot和rabbitmq发送方确认及手动确认_第1张图片

2、初始化队列:

rabbitmq学习7-springboot和rabbitmq发送方确认及手动确认_第2张图片

3、发送方确认回调

public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback {

    private Logger logger= LoggerFactory.getLogger(RabbitConfirmCallback.class);

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            logger.info("消息已确认 cause:{} - {}",correlationData);
        } else {
            logger.info("消息未确认 cause:{} - {}",correlationData);
        }
    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        logger.info("消息被退回 {}" , message.toString());
    }
}

4、生产者

@Controller
@RequestMapping("translationEx")
public class transProducer{

    private Logger logger= LoggerFactory.getLogger(transProducer.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initRabbitTemplate() {
        // 设置生产者消息确认
        rabbitTemplate.setConfirmCallback(new RabbitConfirmCallback());
        rabbitTemplate.setReturnCallback(new RabbitConfirmCallback());
    }

    @RequestMapping("/sendMessage")
    public void send() {
        //发送字符串
        for(int i=0;i<10;i++){
            //该随机数会到达发送方确认的回调方法,用来判断消息是否已经达到队列
            CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
            this.rabbitTemplate.convertAndSend(null,"pConfirm", "a"+i,correlationData);
        }
    }
}

5、消费者

@Component
public class TransCustomer {

    private Logger logger= LoggerFactory.getLogger(TransCustomer.class);

    @RabbitListener(queues="pConfirm")
    public void processA(String msg,Channel channel,Message message) throws IOException {
        logger.info("ReceiveMessage:"+msg);
        try {
            //告诉服务器收到这条消息 已经被我消费了 可以在队列删掉 这样以后就不会再发了 否则消息服务器以为这条消息没处理掉 后续还会再发
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            System.out.println("receiver success");
        } catch (IOException e) {
            e.printStackTrace();
            //丢弃这条消息
            //channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
            //ack返回false,并重新回到队列
            //channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            System.out.println("receiver fail");
        }
    }
}

6、测试

rabbitmq学习7-springboot和rabbitmq发送方确认及手动确认_第3张图片

https://github.com/windyNaruto9833/java-rabbitmq.git

你可能感兴趣的:(rabbitmq学习)