The summary is:
If the message does not reach the exchange, then confirm callback, ack = false
If the message arrives at the exchange, confirm callback, ack = true
Exchange to queue is successful, no return is called
If exchange to queue fails, the callback will be returned (mandatory = true needs to be set, otherwise the callback will not be returned and the message will be lost)
Understand the Confirm message confirmation mechanism:
The confirmation of the message means that after the producer delivers the message, if the broker receives the message, it will give us a response to the production.
The producer receives a response to determine whether the message is normally sent to the broker, which is also the core guarantee for the reliable delivery of the message.
How to implement Confirm confirmation message?
The first step: open the confirmation mode on the channel: channel.confirmSelect ()
The second step: add a listener on the channel: addConfirmListener, monitor the success and failure return results,
Re-send the message or log the follow-up processing according to the specific results.
1 // Production code 2 // 1 Create ConnectionFactory 3 ConnectionFactory connectionFactory = new ConnectionFactory (); 4 connectionFactory.setHost ("127.0.0.1"); 5 connectionFactory.setPort (5672); 6 connectionFactory.setVirtualHost ("/") ; 7 8 // 2 Get Connection 9 Connection connection = connectionFactory.newConnection (); 10 11 // 3 Create a new Channel via Connection 12 Channel channel = connection.createChannel (); 13 14 15 // 4 Specify our Message delivery mode: message confirmation mode 16 channel.confirmSelect (); 17 18 String exchangeName = "test_confirm_exchange"; 19 String routingKey = "confirm.save"; 20 21 //5 发送一条消息 22 String msg = "Hello RabbitMQ Send confirm message!"; 23 channel.basicPublish(exchangeName, routingKey, null, msg.getBytes()); 24 25 //6 添加一个确认监听 26 channel.addConfirmListener(new ConfirmListener() { 27 @Override 28 public void handleNack(long deliveryTag, boolean multiple) throws IOException { 29 System.err.println("-------no ack!-----------"); 30 } 31 32 @Override 33 public void handleAck(long deliveryTag, boolean multiple) throws IOException { 34 System.err.println("-------ack!-----------"); 35 } 36 });
1 // Consumer code 2 // 1 Create ConnectionFactory 3 ConnectionFactory connectionFactory = new ConnectionFactory (); 4 connectionFactory.setHost ("127.0.0.1"); 5 connectionFactory.setPort (5672); 6 connectionFactory.setVirtualHost ("/") ; 7 8 // 2 Get Connection 9 Connection connection = connectionFactory.newConnection (); 10 11 // 3 Create a new Channel via Connection 12 Channel channel = connection.createChannel (); 13 14 String exchangeName = "test_confirm_exchange"; 15 String routingKey = "confirm. #"; 16 String queueName = "test_confirm_queue"; 17 18 // 4 Declare the switch and queue and then set the binding, and finally formulate the routing Key 19 channel.exchangeDeclare (exchangeName, "topic", true); 20 channel.queueDeclare (queueName, true, false, false, null); 21 channel .queueBind (queueName, exchangeName, routingKey); 22 23 // 5 Create consumer 24 QueueingConsumer queueingConsumer = new QueueingConsumer (channel); 25 channel.basicConsume (queueName, true, queueingConsumer); 26 27 while (true) { 28 Delivery delivery = queueingConsumer.nextDelivery (); 29 String msg = new String (delivery.getBody ()); 30 31 System.err.println ("Consumer:" + msg); 32}
Return message mechanism
Return Listener is used to process some non-routable messages.
Our message producer, by specifying an Exchange and Routingkey, sends the message to a certain queue,
Then our consumers listen to the queue and perform message processing operations.
However, in some cases, if we are sending a message, the current exchange does not exist or the specified routing key cannot be routed,
At this time we need to listen to this unreachable message, we must use the return listener.
There is a key configuration item in the basic API:
Mandatory : If it is true, the monitor will receive a message that the route is unreachable, and then perform subsequent processing,
If it is false, then the broker automatically deletes the message. (Default false)
1 //生产端代码 2 ConnectionFactory connectionFactory = new ConnectionFactory(); 3 connectionFactory.setHost("127.0.0.1"); 4 connectionFactory.setPort(5672); 5 connectionFactory.setVirtualHost("/"); 6 7 Connection connection = connectionFactory.newConnection(); 8 Channel channel = connection.createChannel(); 9 10 String exchange = "test_return_exchange"; 11 String routingKey = "return.save"; 12 String routingKeyError = "abc.save"; 13 14 String msg = "Hello RabbitMQ Return Message"; 15 16 17 channel.addReturnListener(new ReturnListener() { 18 @Override 19 public void handleReturn(int replyCode, String replyText, String exchange, 20 String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException { 21 22 System.err.println("---------handle return----------"); 23 System.err.println("replyCode: " + replyCode); 24 System.err.println("replyText: " + replyText); 25 System.err.println("exchange: " + exchange); 26 System.err.println("routingKey: " + routingKey); 27 System.err.println("properties: " + properties); 28 System.err.println("body: " + new String(body)); 29 } 30 }); 31 32 33 channel.basicPublish(exchange, routingKeyError, true, null, msg.getBytes()); 34
//消费端代码 ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("127.0.0.1"); connectionFactory.setPort(5672); connectionFactory.setVirtualHost("/"); Connection connection = connectionFactory.newConnection(); Channel channel = connection.createChannel(); String exchangeName = "test_return_exchange"; String routingKey = "return.#"; String queueName = "test_return_queue"; channel.exchangeDeclare(exchangeName, "topic", true, false, null); channel.queueDeclare(queueName, true, false, false, null); channel.queueBind(queueName, exchangeName, routingKey); QueueingConsumer queueingConsumer = new QueueingConsumer(channel); channel.basicConsume(queueName, true, queueingConsumer); while(true){ Delivery delivery = queueingConsumer.nextDelivery(); String msg = new String(delivery.getBody()); System.err.println("消费者: " + msg); }
operation result: