- message confirmation mechanism
1. From the experimental point of view, the confirmation mechanism of the message only confirms that the publisher sends the message to the broker, and the broker responds, but cannot confirm whether the message is effectively consumed.
2. In order to confirm whether the message is sent to the queue, the parameter mandatory=true should be enabled in the sending message, and the ReturnListener should be used to receive the message that was not sent successfully.
3. Next, you need to confirm whether the message is effectively consumed. The publisher does not currently provide monitoring events, but provides a response mechanism to ensure that the message is successfully consumed. The response method:
basicAck: successful consumption, the message is deleted from the queue
basicNack: requeue=true, the message re-enters the queue, false is deleted
basicReject: Equivalent to basicNack
basicRecover: the message is re-queued, requeue=true, sent to the new consumer, false is sent to the same consumer
- The transaction mechanism of the response mode
package com.demo.mq.rabbitmq.example11; import java.io.IOException; import java.io.Serializable; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; /** * The transaction mechanism of the response mode * @author sheungxin * */ public class TxDemo { private static String exchange_name=""; private static String queue_name="tx_queue"; /** * transaction mechanism to send messages, transaction mechanism: manual commit and rollback * Execute txCommit, the message will be forwarded to the queue to enter the ready state * Execute txRollback, the message is canceled * @param month * @throws Exception */ public static void txSend(Serializable mes) throws Exception{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); //Open the transaction mechanism channel.txSelect(); channel.queueDeclare(queue_name,false,false,true,null); for(int i=0;i<10;i++){ try{ channel.basicPublish(exchange_name, queue_name, null, SerializationUtils.serialize(mes.toString()+i)); //do something // int n=5/0;//Test message rollback channel.txCommit();//Commit message System.out.println("Post message"+mes.toString()+i); }catch(Exception e){ channel.txRollback();//Exception, cancel the message System.out.println("rollback message"+mes.toString()+i); } } } /** * transaction mechanism to receive messages, transaction mechanism: manual commit and rollback * Consumers need to execute basicAck, and txCommit (automatic response mode automatic processing, in this example using manual response mode) * @throws Exception */ public static void txRecv() throws Exception{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); //Open the transaction mechanism channel.txSelect(); channel.queueDeclare(queue_name,false,false,true,null); //Close the automatic answer mode (automatic answer mode does not require ack, txCommit), you need to manually basicAck, and execute txCommit channel.basicConsume(queue_name, false, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{ String mes=SerializationUtils.deserialize(body); System.out.println("tx Received :'"+mes+"' done"); channel.basicAck(envelope.getDeliveryTag(), false); channel.txCommit(); } }); } public static void main(String[] args) throws Exception { txSend("hello world!"); txRecv (); } }
- Confirm mechanism in response mode
2. confirmSelect, enter the confirm message confirmation mode, confirmation methods: 1. Asynchronous ConfirmListener; 2. Synchronous waitForConfirms
3. ConfirmListener, waitForConfirms are required Use with the confirm mechanism
4. I haven't figured out the application of the confirm mechanism in the consumer for the time being. ConfirmListener is invalid in the consumer.
5. basicNack, basicReject: when the parameter requeue=true, the message will re-enter the queue
. Any unprocessed messages will be closed
package com.demo.mq.rabbitmq.example11; import java.io.IOException; import java.io.Serializable; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.Channel; import com.rabbitmq.client.ConfirmListener; import com.rabbitmq.client.Connection; /** * Confirm mechanism in response mode: message sending * @author sheungxin * */ public class ConfirmSend { private static String exchange_name=""; private static String queue_name="tx_queue"; /** * confirm mechanism: confirms that the publisher sends a message to the broker, and the broker responds (cannot confirm whether it is effectively consumed) * confirmSelect, enter the confirm message confirmation mode, confirmation method: 1. Asynchronous ConfirmListener; 2. Synchronous waitForConfirms * ConfirmListener and waitForConfirms need to be used with the confirm mechanism * @param month * @throws Exception */ public static void txSend(Serializable mes) throws Exception{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); //Open the transaction mechanism channel.confirmSelect(); channel.queueDeclare(queue_name,false,false,true,null); //Asynchronously realize the confirmation of sending the message (the message confirmation in this part refers to sending the message to the queue, not the effective consumption of the confirmation message) channel.addConfirmListener(new ConfirmListener() { @Override public void handleNack(long deliveryTag, boolean multiple) throws IOException { //multiple: The test found multiple random true or false, the reason is unknown System.out.println("Nack deliveryTag:"+deliveryTag+",multiple:"+multiple); } @Override public void handleAck(long deliveryTag, boolean multiple) throws IOException { System.out.println("Ack deliveryTag:"+deliveryTag+",multiple:"+multiple); } }); for(int i=0;i<10;i++){ channel.basicPublish(exchange_name, queue_name, null, SerializationUtils.serialize(mes.toString()+i)); } // channel.waitForConfirms();//Confirmation of sending messages synchronously System.out.println("-----------"); channel.close(); conn.close(); } public static void main(String[] args) throws Exception { txSend("hello world!"); } }
package com.demo.mq.rabbitmq.example11; import java.io.IOException; import org.apache.commons.lang3.SerializationUtils; import com.demo.mq.rabbitmq.MqManager; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; /** * Confirm mechanism in response mode: message reception * @author sheungxin * */ public class ConfirmRecv { private static String queue_name="tx_queue"; /** * confirm mechanism: I haven't figured out the application of the confirm mechanism in the consumer for the time being, and the ConfirmListener is invalid in the consumer * basicNack, basicReject: When the parameter requeue=true, the message will re-enter the queue * The autoDelete queue will be closed after the consumer is closed regardless of whether there are still unprocessed messages * @throws Exception */ public static void txRecv() throws Exception{ Connection conn=MqManager.newConnection(); Channel channel=conn.createChannel(); //Open the transaction mechanism // channel.confirmSelect(); //autoDelete, true as long as the message channel.queueDeclare(queue_name,false,false,true,null); //Turn off auto answer mode channel.basicConsume(queue_name, false, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag,Envelope envelope,AMQP.BasicProperties properties,byte[] body) throws IOException{ String mes=SerializationUtils.deserialize(body); //multiple batch submission, true submission is less than the tag message in the parameter long n=envelope.getDeliveryTag()%3; if(n==0){ channel.basicAck(envelope.getDeliveryTag(), false); }else if(n==1){ //requeue, true re-enter the queue channel.basicNack(envelope.getDeliveryTag(), false, true); }else{ //requeue, true re-enter the queue, and the difference from basicNack lacks multiple parameters channel.basicReject(envelope.getDeliveryTag(), true); } try { Thread.sleep(2*1000); } catch (InterruptedException e) { e.printStackTrace (); } System.out.println((n==0?"Ack":n==1?"Nack":"Reject")+" mes :'"+mes+"' done"); } }); } public static void main(String[] args) throws Exception { txRecv (); } }