RabbitMQ usage scenario exercise: delay queue (8)

  • delay queue
     Delayed message sending may be used in actual business scenarios. For example, in payment scenarios, different schemes will be implemented for on-time payment and over-payment, in which time-out and unpaid can be regarded as a delayed message.
     RabbitMQ itself does not have the function of delayed message queue, but it can be implemented through TTL (Time To Live) and DLX (Dead Letter Exchanges) features. The principle is to set the expiration time for the message, and specify the forwarder for the expired message on the message queue, so that after the message expires, it will be forwarded to the queue that matches the specified forwarder, and the direction of the delay queue is realized. Using this feature of RabbitMQ, it should be possible to realize many real-world businesses, and we can use our imagination.
     rabbitmq-delayed-message-exchange , we can also use plugins to implement delayed queues. Can the delay queue implemented by TTL and DLX be interrupted, can the delay queue implemented by using plugins be interrupted? Save for next time. . .

  • Points to Note

Set an expiration time for each message :
Builder properties=new BasicProperties.Builder();
//The specified message expiration time is 12 seconds, and the message expiration time can also be specified on the queue, whichever is smaller.
properties.expiration("12000");//Delayed for 12 seconds, it will not be deleted in time (it is determined whether it expires when consumemr is consumed, because the expiration time of each message is inconsistent, deleting expired messages requires scanning the entire queue)
channel.basicPublish("header_exchange", "" ,properties.build(), SerializationUtils.serialize(object));

Set the queue expiration time (you can not set it), message expiration time, and expired message forwarding rules on the queue :
//Set the message expiration time to 12 seconds, and forward the message to the specified forwarder and matching routingkey when the message expires (can not be specified)
Map<String, Object> args=new HashMap<String, Object>();
args.put("x-expires", 30000);//Queue expiration time
args.put("x-message-ttl", 12000);//The message expiration time on the queue should be less than the queue expiration time
args.put("x-dead-letter-exchange", "exchange-direct");//The expired message is redirected to the route
args.put("x-dead-letter-routing-key", "routing-delay");//The expired message redirects to the route matching the routingkey

The message will expire without consumer consumption, so the consumer in the receiving message class needs to comment out

the message expiration time set on the queue and the message expiration time set on the message. The priority is the smaller

. Set the message expiration time on the queue and set the message on the message. Expiration time, the latter expired messages may not be deleted in time, because the expiration time of each message is inconsistent, and deleting expired messages requires scanning the entire queue, so it is judged whether it expires when consuming

  • send message class

package com.demo.mq.rabbitmq.example08;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.SerializationUtils;

import com.demo.mq.rabbitmq.MqManager;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.AMQP.BasicProperties.Builder;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;

/**
 * Send message class
 * @author sheungxin
 *
 */
public class Send{

	/**
	 * Practice delayed forwarding on the basis of topic forwarders, and specify message expiration time when sending messages
	 * The message has been sent to the queue, but not consumed by the consumer
	 * @param object message body
	 * @throws IOException
	 */
	public static void sendAToB(Serializable object) throws Exception{
		Connection conn=MqManager.newConnection();
		Channel channel=conn.createChannel();
		//declare the headers forwarder
		channel.exchangeDeclare("header_exchange", BuiltinExchangeType.HEADERS);
		//Define the key-value pair stored by headers
		Map<String, Object> headers=new HashMap<String, Object>();
		headers.put("key", "123456");
		headers.put("token", "654321");
		// put the key-value pair in properties
		Builder properties=new BasicProperties.Builder();
		properties.headers(headers);
		properties.deliveryMode(2);//Persistence
		//The specified message expiration time is 12 seconds, and the message expiration time can also be specified on the queue, whichever is smaller.
// properties.expiration("12000");//Delayed for 12 seconds, it will not be deleted in time (it is determined whether it has expired when consuming consumemr, because the expiration time of each message is inconsistent, deleting expired messages requires scanning the entire queue)
		channel.basicPublish("header_exchange", "" ,properties.build(), SerializationUtils.serialize(object));
		System.out.println("Send '"+object+"'");
		channel.close();
		conn.close();
	}
	
	public static void main(String[] args) throws Exception {
		sendAToB("Hello World !");
	}
}

  • receive message class

package com.demo.mq.rabbitmq.example08;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.SerializationUtils;

import com.demo.mq.rabbitmq.MqManager;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 * Receive message class
 * @author sheungxin
 *
 */
public class Recv {
	
	/**
	 * Practice delayed forwarding on the basis of topic forwarders, set queue expiration time (automatically delete after expiration), and expire message processing strategy (forward to matching queue)
	 * After starting the receiving class to create the queue during the experiment, close the thread and make it into an unused state
	 * @throws Exception
	 */
	public static void recvAToB() throws Exception{
		Connection conn=MqManager.newConnection();
		Channel channel=conn.createChannel();
		channel.exchangeDeclare("header_exchange", BuiltinExchangeType.HEADERS);
		//Set the queue expiration time to 30 seconds, and forward the message to the specified forwarder and the matching routingkey when the message expires (can not be specified)
		Map<String, Object> args=new HashMap<String, Object>();
		args.put("x-expires", 30000);//Queue expiration time
		args.put("x-message-ttl", 12000);//The message expiration time on the queue
		args.put("x-dead-letter-exchange", "exchange-direct");//The expired message is redirected to the route
		args.put("x-dead-letter-routing-key", "routing-delay");//The expired message redirects to the route matching the routingkey
		//create a temporary queue
		String queueName=channel.queueDeclare("tmp01",false,false,false,args).getQueue();
		//Specify the matching type of headers (all, any), key-value pair
		Map<String, Object> headers=new HashMap<String, Object>();
		headers.put("x-match", "all");//all any (as long as there is a key-value pair matching)
		headers.put("key", "123456");
//		headers.put("token", "6543211");
		//Bind the temporary queue and forwarder header_exchange
		channel.queueBind(queueName, "header_exchange", "", headers);
		System.out.println("Received ...");
		Consumer consumer=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(envelope.getRoutingKey()+":Received :'"+mes+"' done");
				channel.basicAck(envelope.getDeliveryTag(), false);
			}
		};
		//Turn off the automatic response mechanism, which is enabled by default; at this time, you need to manually perform the response
		channel.basicConsume(queueName, false, consumer);
	}
	
	public static void main(String[] args) throws Exception {
		recvAToB ();
	}

}

  • Delayed message processing class

package com.demo.mq.rabbitmq.example08;

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.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;

/**
 * Delayed message processing class
 * @author sheungxin
 *
 */
public class DelayRecv {

	/**
	 * Create a queue and declare that the consumer is used to process the forwarded delayed messages
	 * @throws Exception
	 */
	public static void delayRecv() throws Exception{
		Connection conn=MqManager.newConnection();
		Channel channel=conn.createChannel();
		channel.exchangeDeclare("exchange-direct", BuiltinExchangeType.DIRECT);
		String queueName=channel.queueDeclare().getQueue();
		channel.queueBind(queueName, "exchange-direct", "routing-delay");
		Consumer consumer=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(envelope.getRoutingKey()+":delay Received :'"+mes+"' done");
			}
		};
		//Turn off the automatic response mechanism, which is enabled by default; at this time, you need to manually perform the response
		channel.basicConsume(queueName, true, consumer);
	}
	
	public static void main(String[] args) throws Exception {
		delayRecv();
	}

}

Guess you like

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