RabbitMQ 高级特性 - 消息的可靠性投递

RabbitMQ 高级特性 - 消息的可靠性投递

  • 使用 RabbitMQ 的时候,作为消息发送方希望杜绝任何消息丢失或者投递失败场景。
  • RabbitMQ 为我们提供了两种方式用来控制消息的投递可靠性模式。
    1. confirm 确认模式
    2. return 退回模式
  • rabbitmq 整个消息投递的路径为:
    • producer--->rabbitmq broker--->exchange--->queue--->consumer
    • 生产者--->rabbitmq中间件--->交换机--->队列--->消费者
      • confirm 模式: 消息从 producer 到 exchange 则会返回一个 confirmCallback
      • return 退回模式: 消息从 exchange–>queue 投递失败则会返回一个 returnCallback

  • confirm 确认模式
    1. 步骤
      1. 创建工程
        在这里插入图片描述

      2. pom.xml导包

         <dependencies>
                <!--spring 上下文-->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>5.1.7.RELEASE</version>
                </dependency>
        
                <!-- spring 整合rabbit-->
                <dependency>
                    <groupId>org.springframework.amqp</groupId>
                    <artifactId>spring-rabbit</artifactId>
                    <version>2.1.8.RELEASE</version>
                </dependency>
        
                <!-- 单元测试-->
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.12</version>
                </dependency>
        
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-test</artifactId>
                    <version>5.1.7.RELEASE</version>
                </dependency>
        
            </dependencies>
        
        
            <build>
                <plugins>
                    <!-- 编译插件包-->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.8.0</version>
                        <configuration>
                            <source>1.8</source>
                            <target>1.8</target>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        
      3. resources目录下创建rabbitmq.properties文件

        rabbitmq.host=192.168.20.146
        rabbitmq.port=5672
        rabbitmq.username=test
        rabbitmq.password=test
        rabbitmq.virtual-host=/test
        
      4. resources目录下创建spring-rabbitmq-producer.xml文件

        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
               xmlns:rabbit="http://www.springframework.org/schema/rabbit"
               xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               https://www.springframework.org/schema/context/spring-context.xsd
               http://www.springframework.org/schema/rabbit
               http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
            <!--加载配置文件-->
            <context:property-placeholder location="classpath:/rabbitmq.properties"/>
        
            <!-- 定义rabbitmq connectionFactory -->
            <rabbit:connection-factory id="connectionFactory" host="${rabbitmq.host}"
                                       port="${rabbitmq.port}"
                                       username="${rabbitmq.username}"
                                       password="${rabbitmq.password}"
                                       virtual-host="${rabbitmq.virtual-host}"/>
            <!--定义管理交换机、队列-->
            <rabbit:admin connection-factory="connectionFactory"/>
        
            <!--定义rabbitTemplate对象操作可以在代码中方便发送消息-->
            <rabbit:template id="rabbitTemplate" connection-factory="connectionFactory"/>
        </beans>
        
      5. spring-rabbitmq-producer.xml文件创建队列和交换机

            <!-- 1. 创建队列 -->
            <rabbit:queue id="test_queue_confirm" name="test_queue_confirm"/>
            <!-- 2. 创建交换机 -->
            <rabbitmq:direct-exchange name="test_exchange_confirm">
                <rabbit:bindings>
                    <rabbit:binding queue="test_queue_confirm" key="confirm"/>
                </rabbit:bindings>
            </rabbitmq:direct-exchange>
        
      6. 创建测试类
        在这里插入图片描述

        package com.yang.test;
        
        import org.junit.runner.RunWith;
        import org.springframework.amqp.rabbit.core.RabbitTemplate;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.test.context.ContextConfiguration;
        import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
        
        @RunWith(SpringJUnit4ClassRunner.class)
        @ContextConfiguration(locations = "classpath:spring-rabbitmq-producer.xml")
        public class ProducerTest {
        
            @Autowired
            private RabbitTemplate rabbitTemplate;
            
        }
        
      7. 编写确认模式步骤

        1. ConnectionFactory中开启配置(在配置文件里面)
          在这里插入图片描述

        2. 在rabbitmqTemplate定义ConfirmCollBack回调函数

          @Test
              public void testConfirm() {
                  //2. 定义回调函数
                  rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
                      @Override
                      public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                          System.out.println("confirm方法被执行了....");
                      }
                  });
              }
          
        3. 发送消息测试一下

           @Test
              public void testConfirm() {
                  //2. 定义回调函数
                  rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
                      @Override
                      public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                          System.out.println("confirm方法被执行了....");
                      }
                  });
                  //3. 发送消息
                  rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","message confirm ...");
              }
          
        4. 尝试执行一下(此时回调函数会执行,并且消息也在队列里面了)
          在这里插入图片描述
          在这里插入图片描述

        5. public void confirm(CorrelationData correlationData, boolean ack, String cause)参数详解

           			/**
                       *
                       * @param correlationData 相关配置信息
                       * @param ack   代表exchange交换机是否成功收到消息.true 收到, false 没收到
                       * @param cause 失败的原因
                       */
          
        6. 尝试执行(成功的和失败(故意把交换机名称写错test1_exchange_confirm))

          @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) {
                          if (ack) {
                              System.out.println("接受消息成功");
                          }else {
                              System.out.println("接受消息失败"+cause);
                          }
                          System.out.println("confirm方法被执行了....");
                      }
                  });
                  //3. 发送消息
                  rabbitTemplate.convertAndSend("test_exchange_confirm","confirm","message confirm ...");
              }
          
          

          在这里插入图片描述
          在这里插入图片描述

        7. 我们也可以直接通过lambda表达式来写回调函数

          		rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{
          
                  });
          

  • return 退回模式
    1. 步骤(1-6都是一样的)
      1. 编写回退模式步骤
        1. ConnectionFactory中开启配置(在配置文件里面)
          在这里插入图片描述

        2. 设置对应的ReturnCallBack(直接用lambda表达式)此时默认是丢弃,下面这句话是不会执行的!!!使用了不存在的routingKeyconfirm1

          	@Test
              public void testReturn() {
                  //2. 设置对应的ReturnCallBack
                  rabbitTemplate.setReturnCallback((message, replyCode, replyText ,exchange, routingKey)->{
                      System.out.println("return 执行了....");
                  });
                  //3. 发送消息
                  rabbitTemplate.convertAndSend("test1_exchange_confirm","confirm","message confirm ...");
              }
          

          在这里插入图片描述

        3. 设置Exchange处理消息的模式rabbitTemplate.setMandatory(true):

          1. 如果消息没有路由到Queue,则丢弃消息(默认)

          2. 如果消息没有路由到Queue,返回给消息发送方ReturnCallBack

            	@Test
                public void testReturn() {
                    // 设置交换机处理失败消息的模式
                    rabbitTemplate.setMandatory(true);
                    //2. 设置对应的ReturnCallBack
                    rabbitTemplate.setReturnCallback((message, replyCode, replyText ,exchange, routingKey)->{
                        System.out.println("return 执行了....");
                    });
                    //3. 发送消息
                    rabbitTemplate.convertAndSend("test_exchange_confirm","confirm1","message confirm ...");
                }
            
          3. 运行结果
            在这里插入图片描述

          4. public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey)参数详解

            		/**
                     *
                     * @param message 消息对象
                     * @param replyCode 失败的错误码
                     * @param replyText 错误信息
                     * @param exchange 交换机
                     * @param routingKey 路由键
                     */
            

  • 消息的可靠投递小结
    • 设置ConnectionFactory的publisher-confirms=“true” 开启 确认模式。

    • 使用rabbitTemplate.setConfirmCallback设置回调函数。当消息发送到exchange后回调confirm方法。在方法中判断ack,如果为true,则发送成功,如果为false,则发送失败,需要处理。

    • 设置ConnectionFactory的publisher-returns=“true” 开启 退回模式。

    • 使用rabbitTemplate.setReturnCallback设置退回函数,当消息从exchange路由到queue失败后,如果设置了rabbitTemplate.setMandatory(true)参数,则会将消息退回给producer。并执行回调函数returnedMessage。

    • 在RabbitMQ中也提供了事务机制,但是性能较差。

      • 使用channel下列方法,完成事务控制:
        1. txSelect(), 用于将当前channel设置成transaction模式
        2. txCommit(),用于提交事务
        3. txRollback(),用于回滚事务
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值