RabbitMQ提升消息可靠性的方法

mandatory参数

当mandatory参数设置为true的时候,交换器无法根据自身的类型和路由键找到一个符合条件的队列,那么RabbitMQ会调用Basic.Return命令将消息返回给生产者。当mandatory参数设置为false时,出现上述情形,则消息直接被丢弃。

生产者是如何获取到没有被正确路由到合适的队列的消息呢?可以通过调用channel.addReturnListener来添加ReturnListener监听器实现。示例部分代码如下:

//创建信道
        Channel channel = connection.createChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"direct",true,false,null);
        channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY);
        String message = "Hello Rabbitmq";
        channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,true, MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
        channel.addReturnListener(new ReturnListener() {
            @Override
            public void handleReturn(int i, String s, String s1, String s2, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
                String message = new String(bytes);
                System.out.println("Basic Return 返回的结果是:" + message);
            }
        });

上述代码中生产者如果没有成功的将消息路由到队列,此时RabbitMQ会通过Basic.Return来返回“Hello Rabbitmq”这条消息,之后生产者客户端通过ReturnListener监听到了这个事件,上述代码运行的结果是:Basic Return 返回的结果是:Hello Rabbitmq。

备份交换器

备份交换器,英文名称为Alternate Exchange,简称AE,或者更直白的称之为“备胎交换器”。可以通过在声明交换器(调用channel.exchangeDeclare方法)的时候添加alternate-exchange参数来实现,也可以通过策略的方式实现,如果同时使用则前者的优先级更高,会覆盖掉Policy的设置。

      //创建信道
        Channel channel = connection.createChannel();
        //设置备份交换器的参数
        Map<String,Object> arg = new HashMap<String, Object>();
        arg.put("alternate","myAe");
        channel.exchangeDeclare("normalExchange","direct",true,false,arg);
        channel.exchangeDeclare("myAe","fanout",true,false,null);
        channel.queueDeclare("normalQueue",true,false,false,null);
        channel.queueBind("normalQueue","normalExchange","normalKey");
        channel.queueDeclare("unroutrdQueue",true,false,false,null);
        channel.queueBind("unroutrdQueue","myAe","");

上述代码中声明了两个交换器的normalExchange和myAe,分别绑定了noemalQueue和unroutrdQueue这两个队列,同时将myAe设置为normalExchange的备份交换器,注意myAe的交换器类型为fanout。如下图:

同样,可以采用Policy的方式设置备份交换器,可以参考如下:

rabbitmqctl set_policy AE "^normalExchange$" `{"alternate-exchange": "myAe"}`

备份交换器其实和普通的交换器没有太大的区别,为了方便使用,建议设置为fanout类型,如若想设置为direct或者topic的类型的也没有什么不可以的。需要注意的是,消息被重发到备份交换器时路由键和从生产者发出的路由键是一样的

对于备份交换器,存在以下几种特殊的情况:

  ❤ 如果设置的备份交换器不存在,客户端和RabbitMQ服务端都不会有异常出现,此时消息会丢失。

  ❤ 如果备份交换器没有绑定任何队列,客户端和RabbitMQ服务端不会有异常出现,此时消息会丢失。

  ❤ 如果备份交换器没有任何匹配的队列,客户端和RabbitMQ都不会有异常出现,此时消息会丢失。

  ❤ 如果备份交换器和mandatory参数一起使用,那么mandatory参数无效。

参考:《RabbitMQ实战指南》 朱忠华  著;

posted on 2019-05-21 08:18  AoTuDeMan  阅读(267)  评论(0编辑  收藏  举报

导航