RabbitMQ usage scenario exercise: message confirmation mechanism (11)

  • message confirmation mechanism
RabbitMQ provides two message confirmation mechanisms, transaction and confirm. Transaction is a transaction mechanism, which is manually submitted and rolled back; the confirm mechanism provides two methods: Confirmlistener and waitForConfirms. The efficiency of the confirm mechanism is obviously higher than that of the transaction mechanism, but the advantage of the latter is strong consistency. If there are no special requirements, it is recommended to use the conrim 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
Manual submission and rollback are required. After executing txCommit, the message will be forwarded to the queue to enter the ready state; if txRollback is executed, the message will be cancelled.
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
1. Confirm that the publisher sends a message to the broker, and the broker responds (can not confirm whether it is effectively consumed)
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 ();
	}
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326945082&siteId=291194637