java使用RabbitMQ(二)

1、RabbitMQ消息确认机制-可靠抵达

前言:为了保证消息不丢失,可靠抵达,可以使用事务消息(客户端与broker建立连接在通道中进行收发消息,设置通道为事务模式,只有当发送成功,或者消费成功,mq给出响应等一连串反应成功之后才算成功),但是官方说性能会下降250倍,为了保证高并发,所以就引入了消息的确认机制
eg:publisher发送给broker,网络波动没发成功,发成功了broker没接收到,consumer消费一半网络波动导致消息没接收到等各种场景
保证可靠抵达就是保证消息可靠的发送到broker以及consumer可靠的消费这条消息
在这里插入图片描述

1.1可靠抵达-confirmCallback

spring.rabbitmq.publisher-confirm-type=correlated
①在创建connectFactory的时候设置PublisherConfirm(true)选项,开启confirmCallback
②CorrelationData:用来表示当前消息唯一性
③消息只要被broker接收到就会执行confirmCallback,如果是cluster模式,需要所有broker接受到才会调用confirmCallback
④被broker接收到只能标识message已经抵达服务器,并不能保证消息一定会投递到queue中,所以需要用到E->Q的确认机制(只要投递失败就会触发returnCallback方法)

1.2可靠抵达-returnCallback

spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true
①confirm模式只能保证消息抵达broker,不能保证消息准确投递到目标queue中,在有些业务场景下,我们需要保证消息一定要投递到目标queue中,此时就需要returnCallback退回模式
②这样如果未能投递到目标queue里将调用returnCallback,可以记录下详细要投递的数据,定期巡查或者自动纠错都需要这些数据

1.3可靠抵达-Ack消息确认机制

①消费者获取到消息,成功处理,可以恢复Ack给Broker
basic.ack用于肯定确认,broker将移除此消息
basic.nack用于否定确认,可以指定broker是否丢弃此消息,可以批量
basic.reject用于否定确认,可以指定broker是否丢弃此消息,但是不能批量
②默认消息被消费者收到,就会从broker的queue中移除
③queue无消费者,消息依然会被存贮,直到消息被消费者消费
④消费者收到消息,默认会自动ack,但是如果无法确认此消息是否被处理完成或者成功处理,可以开启手动ack模式
消息处理成功,ack(),接受下一个消息,此消息会被broker移除
消息处理失败,nack()/reject(),重新发送给其他人进行处理,或者容错处理后ack
消息一直没调用ack()/nack()方法,broker认为此消息正在被处理,不会投递给别人,此时客户端断开,消息不会被broker移除,会投递给别人

import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class MyRabbitConfig {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 使用JSON序列化机制,进行消息转换
     */
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 定制RabbitTemplate 实现自己的消息确认机制
     * 1、服务器收到消息就会回调
     *      1.1 spring.rabbitmq.publisher-confirms=true
     *      1.2 设置确认回调ConfirmCallback
     * 2、消息正确抵达队列进行回调
     * 3、消费端确认(保证每一个消息被正确消费,此时broker才可以删除这个消息)
     *      3.1默认是自动确认的,只要消息接收到,客户端会自动确认,服务端就会移除这个消息
     *      问题:收到一个消息处理成功后,宕机了,所有消息都会丢失,因为自动确认了,所以要手动确认
     *      手动确认模式下,只要美誉哦明确告诉mq货物已被签收,相当于没有ack消息就一直是unacked状态,即使服务器宕机,消息也不会丢失,会重新变为read状态
     *      3.2如何签收 channel.basicAck(deliveryTag, false);
     */
    // MyRabbitConfig对象创建完成后,执行这个方法
    @PostConstruct
    public void initRabbitTemplate() {

        // 设置确认回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             * @param correlationData 当前消息的唯一关联数据(消息的唯一id)
             * @param ack 消息是否成功收到
             * @param cause 失败的原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confirm...correlationData[" + correlationData + "]==>ack[" + ack + "]==>cause[" + cause + "]");
            }
        });

        // 设置消息抵达队列的确认回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            /**
             * 只要消息美誉哦投递给指定的队列就会触发回调,类似于失败回调
             */
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println("投递失败的消息详细信息"+returnedMessage.getMessage());
                System.out.println("回复的状态码"+returnedMessage.getReplyCode());
                System.out.println("回复的文本内容"+returnedMessage.getReplyText());
                System.out.println("当时这个消息发送给哪个交换机"+returnedMessage.getExchange());
                System.out.println("当时这个消息用的哪个路由键"+returnedMessage.getRoutingKey());
                System.out.println("fail message");
            }
        });
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值