rabbitmq學習7-springboot和rabbitmq發送方確認及手動確認

正常情況下,如果消息經過交換器進入隊列就可以完成消息的持久化,但如果消息在沒有到達broker之前出現意外,那就造成消息丟失,有沒有辦法可以解決這個問題?

RabbitMQ有兩種方式來解決這個問題:

一、通過AMQP提供的事務機制實現;

二、使用發送者確認模式實現

如下爲使用發送發確認來保證隊列到達隊列

1、開啓發送發確認,及開啓消息手動確認

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、測試

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章