RabbitMQ的高级特性(更新中)

1消息的可靠性传递

使用rabbitMQ时,消息的发送方希望杜绝然和消息丢失的失败场景。RabbitMQ为我们提供了两种方式来控制消息的可靠性传递模式

  • confirm  确认模式
  • return  退回模式

rabbitMQ消息的传递过程-->

producer-->rabbbimq broker -->exchange-->queue-->consumer

生产者将消息传递给rabbitMQ broker中间件之后,会放入到exchange中,再经过路由信息,将消息放入到指定的队列中,消费者监听指定的队列,来获取消息。

  • confirm 确认模式指的是消息从producer到exchange过程中都会调用一个回调函数confirmCallback。如果消息成功收到则返回true,如果没成功收到则返回false(不管消息是都否都成功到达,都会调用回调函数)
  • return 从exchange到queue中,消息传递失败则会返回一个returnCallback

利用这两个Callback控制消息的可靠性传递

spring整合rabbitmq链接:

Spring整合RabbitMQ,一看就懂_狗头实习生的博客-CSDN博客

1.1实现confirm确认:

定义交换机以及指定队列

<!--        加载配置类-->
    <context:property-placeholder location="classpath:rabbitmq.properties"/>

<!--    定义rabbitmq 连接工厂-->
    <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                               port="${rabbitmq.port}"
                               username="${rabbitmq.username}"
                               password="${rabbitmq.password}"
                               virtual-host="${rabbitmq.virtual-host}"
                               publisher-confirms="true"
                               publisher-returns="true"
    />
<!--    定义管理交换机、队列-->
    <rabbit:admin connection-factory="connectionFactory"/>

    <!--    定义rabbitTemplate对象操作可以在代码中方便发送消息-->
    <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>

<!--    消息的可靠性投递(生产端)-->
    <rabbit:queue id="test_queue_confirm" name="test_queue_confirm"/>
    
<!--    定义交换机-->
    <rabbit:direct-exchange name="test_exchange_confirm">
        <rabbit:bindings>
            <rabbit:binding queue="test_queue_confirm" key="confirm"></rabbit:binding>
        </rabbit:bindings>
    </rabbit:direct-exchange>
    

注意开启confirm和return需要开启publisher-confirms="true" publisher-returns="true"配置。

模拟生产者发送消息:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml")
public class Producer {

    //1.注入RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 确认模式:
     *     步骤:
     *          1.开启确认模式:ConnectionFactory中开启publisher-confirms="true"
     *          2.在rabbitTemplate定义ConfirmCallBack回调函数
     */
    @Test
    public void testConfirm(){
        //2.定义回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             *
             * @param correlationData :相关的配置信息
             * @param ack   :exchange交换机 是否成功收到消息。 true成功 false失败
             * @param cause :失败原因
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confirm方法被执行了....");

                if(ack){
                    //接收成功
                    System.out.println("消息接收成功");
                }else {
                    //接收成功
                    System.out.println("消息接收失败"+cause);
                    //处理一下,让消息再次发送
                }
            }
        });

        //3.发送消息
        rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","message confirm....");

    }

}

1.2实现returnCallback:

public class Producer {

    //1.注入RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     *回退模式:当消息发送给Exchange后,Exchange路由到Queue失败时,才会执行ReturnCallBack
     * 步骤:
     * 1.开启回退模式
     * 2.设置ReturnCallBack
     * 3.设置Exchange处理消息的模式:
     *      1.如果消息没有路由到Queue,则丢弃消息(默认)
     *      2.如果消息没有路由到Queue,则返回给消息的发送方ReturnCallBack
     */
    @Test
    public void testReturn(){

        //设置交换机处理消息失败的模式
        rabbitTemplate.setMandatory(true);

        /**
         * message  :消息对象
         * replyCode :错误码
         * replyText :错误信息
         * exchange  :交换机
         * routingKey:路由键
         */
        //2.设置returnCallBack
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            System.out.println("return执行了...");
            System.out.println(message);
            System.out.println(replyCode);
            System.out.println(replyText);
            System.out.println(exchange);
            System.out.println(routingKey);
        });


        //3.发送消息
        rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","message confirm....");

    }

}

 只有在找不到路由名字写错或者程序内部出现问题时,才会执行returnCallBack方法

1.3消息的可靠投递小结

设置ConnectionFactory的publisher-confirms="true" 开启确认模式

使用rabbitTemplate.setConfirmCallback设置函数回调,消息发到交换机后回调函数,

ack为true,则发送成功,ack为false,则发送失败。

设置ConnectionFactory的publisher-returns="true" 开启退回模式

使用rabbitTemplate.setReturnCallback 设置回退函数,当消息从路由到队列失败时,如果设置了rabbitTemplate.setMandatory(true),会将消息退回给producer,并执行回调函数

1.4Consumer 确认

ack指Acknowledge。表示消费端收到消息后确认方式

有三种确认方式:

  • 自动确认:acknowledge = "none" (收到消息后自动确认,若程序是否出现异常可能会丢失消息)
  • 手动确认:acknowledge = "manual" (收到消息后,手动确认,如果出现异常,可以请求消息队列重新发送)
  • 根据异常情况确认:acknowledge = "auto"(使用情况很复杂,根据抛异常的类型做处理)

自动确认消息一旦呗Consumer接收到,则自动确认,将相应的message从RabbitMQ消息缓存中移除,如果业务处理出现异常,则会丢失消息。

手动确认业务处理成功后调用channel.basicAck()手动签收,如果出现异常,则调用channel.basicNack()方法,让消息自动重新发送。

手动确认

客户端设置手动确认,业务逻辑正常处理完之后,手动确认签收,否则拒绝签收数据,要求broker重新发送数据。

@Component
public class AckListener implements ChannelAwareMessageListener {

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        Thread.sleep(1000);
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        System.out.println("~~~~~~~~");
        try {
            //1.接受转换消息

            System.out.println(new String(message.getBody()));

            //2.处理业务逻辑
            System.out.println("处理业务逻辑。。。。");
            // int i = 3/0;
            //3.手动签收
            /**
             * deliveryTag:消息标签
             * true:可以同时处理多条消息
             */
            channel.basicAck(deliveryTag, true);
        }catch (Exception e){
            //4.拒绝签收
            /**
             * 第三个参数:设置为true,则消息重新回到queue,broker会重新发送消息给消费端
             */
            channel.basicNack(deliveryTag,true,true);

        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗头实习生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值