當mandatory參數設置爲true的時候,交換器沒法根據自身的類型和路由鍵找到一個符合條件的隊列,那麼RabbitMQ會調用Basic.Return命令將消息返回給生產者。當mandatory參數設置爲false時,出現上述情形,則消息直接被丟棄。ide
生產者是如何獲取到沒有被正確路由到合適的隊列的消息呢?能夠經過調用channel.addReturnListener來添加ReturnListener監聽器實現。示例部分代碼以下:spa
//建立信道 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。code
備份交換器,英文名稱爲Alternate Exchange,簡稱AE,或者更直白的稱之爲「備胎交換器」。能夠經過在聲明交換器(調用channel.exchangeDeclare方法)的時候添加alternate-exchange參數來實現,也能夠經過策略的方式實現,若是同時使用則前者的優先級更高,會覆蓋掉Policy的設置。orm
//建立信道 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。以下圖:blog
一樣,能夠採用Policy的方式設置備份交換器,能夠參考以下:rabbitmq
rabbitmqctl set_policy AE "^normalExchange$" `{"alternate-exchange": "myAe"}`隊列
備份交換器其實和普通的交換器沒有太大的區別,爲了方便使用,建議設置爲fanout類型,如若想設置爲direct或者topic的類型的也沒有什麼不能夠的。須要注意的是,消息被重發到備份交換器時路由鍵和從生產者發出的路由鍵是同樣的。事件
對於備份交換器,存在如下幾種特殊的狀況:路由
❤ 若是設置的備份交換器不存在,客戶端和RabbitMQ服務端都不會有異常出現,此時消息會丟失。get
❤ 若是備份交換器沒有綁定任何隊列,客戶端和RabbitMQ服務端不會有異常出現,此時消息會丟失。
❤ 若是備份交換器沒有任何匹配的隊列,客戶端和RabbitMQ都不會有異常出現,此時消息會丟失。
❤ 若是備份交換器和mandatory參數一塊兒使用,那麼mandatory參數無效。
參考:《RabbitMQ實戰指南》 朱忠華 著;