When the messages in the queue expire, or reach the maximum length and are deleted, or reach the maximum space and are deleted, the deleted information can be pushed to other switches, and other consumers can subscribe to the deleted messages and process them.
Preparation elements: a producer, a normal consumer (with a normal switch, a routing key, a normal queue) and a consumer (with a death switch, a death routing key, a death queue) who processes expired messages
Producer:
@Component public class MsgProducer { //Switch name private static final String EXCHANGE_NAME = "amqp-hello"; private static final String EXCHANGE_NAME2 = "amqp-hello2"; //Key "mqkey" bound between switch and switch private static final String ExCHANEROUTING_KEY = "mqkey"; //Column names private static final String QUEUE_NAME = "Hello-Queue1"; //routingkey name private static final String ROUTING_KEY = "key-Queue"; //Dead routing key private static final String DEADROUTING_KEY = "deadkey-Queue"; //Death switch private static final String DEADEXCHANGE_NAME = "deadamqp-hello"; //The name of the opposite column to process the death message private static final String DEADQUEUE_NAME = "deadHello-Queue1"; public static void main(String[] args) throws Exception{ String message; //1. Get connection Connection connection = RabbitConnectionUtil.getConnection("localhost", 5672, "/", "guest", "guest"); //2. Declaration channel Channel channel = connection.createChannel(); //Switch channel.exchangeDeclare(EXCHANGE_NAME, "direct", false, false, null); Map<String, Object> arguments = new HashMap<String, Object>(); arguments.put("x-message-ttl", 15000); //Connect the two switches together through these two parameters!! arguments.put("x-dead-letter-exchange", DEADEXCHANGE_NAME); arguments.put("x-dead-letter-routing-key", DEADROUTING_KEY); //3. Declare (create) queue B: whether the durable is persistent or not. The declaration of queue is stored in memory by default. If true: rabbitmq restarts the queue, it will not be lost, but the message is missing. false: the queue and the message are all gone //b1:exclusive: exclusive or not. It has two functions. One is whether the queue will be deleted automatically when the connection is closed //b2:autoDelete: delete automatically. When the last consumer disconnects, the messages in the queue will be deleted automatically. When consumers = 0, the messages in the queue will be deleted automatically channel.queueDeclare(QUEUE_NAME,true,false,false,arguments); //Bind the switch and queue to the switch connected to the queue with exchange [name] through the routing key channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY); //Death switch channel.exchangeDeclare(DEADEXCHANGE_NAME, "direct", false, false, null); //Queue of death information channel.queueDeclare(DEADQUEUE_NAME,true,false,false,null); //Bind the dead switch and the dead letter queue with the dead route key. Deadexchange [name] is the dead switch connected to the dead letter queue channel.queueBind(DEADQUEUE_NAME,DEADEXCHANGE_NAME,DEADROUTING_KEY); for (int i=0;i<20;i++){ //4. Define message content message = "hello rabbitmq-"; //5. When publishing messages, routingkey is used to specify how to assign information to multiple consumers //Basic properties props -- the basic properties of a message, such as routing headers. byte[] body -- message body //void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException; //Note that exchange [name] here is the switch connected to the producer!! Messageproperties.persistent'text'plan represents message persistence (there are other ways to set persistence for several messages separately) channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY,null,(message+i).getBytes()); System.out.println("[x] send'" + (message+i).toString() + "'"); }; //6. Close channels and connections channel.close(); connection.close(); } } }
The key codes are as follows:
Deadexhange? Name
Routing key: routing key
Map<String, Object> arguments = new HashMap<String, Object>(); arguments.put("x-message-ttl", 15000); //Connect the two switches together through these two parameters!! arguments.put("x-dead-letter-exchange", DEADEXCHANGE_NAME); arguments.put("x-dead-letter-routing-key", DEADROUTING_KEY); //Death switch, put the death route key into the normal queueDeclare channel.queueDeclare(QUEUE_NAME,true,false,false,arguments);
Consumer MsgReceiver1 processing normal messages:
@Component public class MsgReceiver1 { //Switch name private static final String EXCHANGE_NAME = "amqp-hello"; private static final String EXCHANGE_NAME2 = "amqp-hello2"; //Key "mqkey" bound between switch and switch private static final String ExCHANEROUTING_KEY = "mqkey"; //Column names private static final String QUEUE_NAME = "Hello-Queue1"; //routingkey name private static final String ROUTING_KEY = "key-Queue"; //Dead routing key private static final String DEADROUTING_KEY = "deadkey-Queue"; //Death switch private static final String DEADEXCHANGE_NAME = "deadamqp-hello"; //The name of the opposite column to process the death message private static final String DEADQUEUE_NAME = "deadHello-Queue1"; public static void main(String[] args) throws Exception { Connection connection = RabbitConnectionUtil.getConnection("127.0.0.1", 5672, "/", "guest", "guest"); Channel channel = connection.createChannel(); Map<String, Object> arguments = new HashMap<String, Object>(); arguments.put("x-message-ttl", 15000); //Connect the two switches together through these two parameters!! arguments.put("x-dead-letter-exchange", DEADEXCHANGE_NAME); arguments.put("x-dead-letter-routing-key", DEADROUTING_KEY); //3. Declaration queue channel.queueDeclare(QUEUE_NAME, true, false, false, arguments); //You need to set the principle that every time you get the number of messages from the queue, you can have more than one job. You can't stop when you're done quickly! channel.basicQos(1); // channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY1); // channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY2); //4. Define the consumers of the queue QueueingConsumer queueingConsumer1 = new QueueingConsumer(channel); /* true:Indicates automatic confirmation. As long as the message is obtained from the queue, whether or not the consumer successfully consumes the message after obtaining it, the message will be considered as successfully consumed false:Indicates manual confirmation. After the consumer obtains the message, the server will mark the message as unavailable and wait for the consumer's feedback, If the consumer has not responded, the message will remain unavailable, and the server will think that the consumer has hung up and will not send a message to him, Until the consumer feedback. For example: channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); */ //b:ack channel.basicConsume(QUEUE_NAME, false,queueingConsumer1); // channel.basicConsume(QUEUE_NAME,true,queueingConsumer2); //6. Get message while (true) { anInt += 1; QueueingConsumer.Delivery delivery1 = queueingConsumer1.nextDelivery(); // QueueingConsumer.Delivery delivery2 = queueingConsumer2.nextDelivery(); String message1 = new String(delivery1.getBody()); // String message2 = String.valueOf(delivery2.getBody()); System.out.println("[" + String.valueOf(anInt) + "]:receve msg:" + message1); //Manually confirm whether the ACK is processed in batch. true: all messages smaller than deliveryTag will be ack once channel.basicAck(delivery1.getEnvelope().getDeliveryTag(), false); // System.out.println("[x] Received '" + message2 + "'"); Thread.sleep(500); } } }
Consumer handling expired messages MsgReceiver2
@Component public class MsgReceiver2 { private static int anInt = 0; //Switch name private static final String EXCHANGE_NAME = "amqp-hello"; private static final String EXCHANGE_NAME2 = "amqp-hello2"; //Key "mqkey" bound between switch and switch private static final String ExCHANEROUTING_KEY = "mqkey"; //Column names private static final String QUEUE_NAME = "Hello-Queue1"; //routingkey name private static final String ROUTING_KEY = "key-Queue"; //Dead routing key private static final String DEADROUTING_KEY = "deadkey-Queue"; //Death switch private static final String DEADEXCHANGE_NAME = "deadamqp-hello"; //The name of the opposite column to process the death message private static final String DEADQUEUE_NAME = "deadHello-Queue1"; //routingkey name // private static final String ROUTING_KEY1 = "key1-Queue"; private static final String ROUTING_KEY2 = "key2-Queue"; public static void main(String[] args) throws Exception { Connection connection = RabbitConnectionUtil.getConnection("127.0.0.1", 5672, "/", "guest", "guest"); Channel channel = connection.createChannel(); //3. Declaration queue channel.queueDeclare(DEADQUEUE_NAME, true, false, false, null); //When polling, you need to set the principle that every time you get the number of messages from the queue, you can have more than one job. You can't stop when you're done quickly! Poll required //This doesn't work channel.basicQos(1); // channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY1); // channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY2); //4. Define the consumers of the queue QueueingConsumer queueingConsumer1 = new QueueingConsumer(channel); /* true:Indicates automatic confirmation. As long as the message is obtained from the queue, whether or not the consumer successfully consumes the message after obtaining it, the message will be considered as successfully consumed false:Indicates manual confirmation. After the consumer obtains the message, the server will mark the message as unavailable and wait for the consumer's feedback, If the consumer has not responded, the message will remain unavailable, and the server will think that the consumer has hung up and will not send a message to him, Until the consumer feedback. For example: channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); */ //b:ack channel.basicConsume(DEADQUEUE_NAME, false, queueingConsumer1); // channel.basicConsume(QUEUE_NAME,true,queueingConsumer2); //6. Get message while (true) { anInt += 1; QueueingConsumer.Delivery delivery1 = queueingConsumer1.nextDelivery(); // QueueingConsumer.Delivery delivery2 = queueingConsumer2.nextDelivery(); String message1 = new String(delivery1.getBody()); // String message2 = String.valueOf(delivery2.getBody()); System.out.println("[" + String.valueOf(anInt) + "]:receve msg:" + message1); //Manually confirm whether the ACK is processed in batch. true: all messages smaller than deliveryTag will be ack once channel.basicAck(delivery1.getEnvelope().getDeliveryTag(), false); // System.out.println("[x] Received '" + message2 + "'"); Thread.sleep(500); } }
Start with multiple consumers and start with producers. Finally, after running the producer, it is found that MsgReceiver2 is waiting. When MsgReceiver1 consumes the normal message, the expired message MsgReceiver2 will start to consume
Operation result:
50 producers
[x] send'hello rabbitmq-0' [x] send'hello rabbitmq-1' [x] send'hello rabbitmq-2' [x] send'hello rabbitmq-3' [x] send'hello rabbitmq-4' [x] send'hello rabbitmq-5' [x] send'hello rabbitmq-6' [x] send'hello rabbitmq-7' [x] send'hello rabbitmq-8' [x] send'hello rabbitmq-9' [x] send'hello rabbitmq-10' [x] send'hello rabbitmq-11' [x] send'hello rabbitmq-12' [x] send'hello rabbitmq-13' [x] send'hello rabbitmq-14' [x] send'hello rabbitmq-15' [x] send'hello rabbitmq-16' [x] send'hello rabbitmq-17' [x] send'hello rabbitmq-18' [x] send'hello rabbitmq-19' [x] send'hello rabbitmq-20' [x] send'hello rabbitmq-21' [x] send'hello rabbitmq-22' [x] send'hello rabbitmq-23' [x] send'hello rabbitmq-24' [x] send'hello rabbitmq-25' [x] send'hello rabbitmq-26' [x] send'hello rabbitmq-27' [x] send'hello rabbitmq-28' [x] send'hello rabbitmq-29' [x] send'hello rabbitmq-30' [x] send'hello rabbitmq-31' [x] send'hello rabbitmq-32' [x] send'hello rabbitmq-33' [x] send'hello rabbitmq-34' [x] send'hello rabbitmq-35' [x] send'hello rabbitmq-36' [x] send'hello rabbitmq-37' [x] send'hello rabbitmq-38' [x] send'hello rabbitmq-39' [x] send'hello rabbitmq-40' [x] send'hello rabbitmq-41' [x] send'hello rabbitmq-42' [x] send'hello rabbitmq-43' [x] send'hello rabbitmq-44' [x] send'hello rabbitmq-45' [x] send'hello rabbitmq-46' [x] send'hello rabbitmq-47' [x] send'hello rabbitmq-48' [x] send'hello rabbitmq-49'
MsgReceiver1 normally processes 31
[1]:receve msg:hello rabbitmq-0 [2]:receve msg:hello rabbitmq-1 [3]:receve msg:hello rabbitmq-2 [4]:receve msg:hello rabbitmq-3 [5]:receve msg:hello rabbitmq-4 [6]:receve msg:hello rabbitmq-5 [7]:receve msg:hello rabbitmq-6 [8]:receve msg:hello rabbitmq-7 [9]:receve msg:hello rabbitmq-8 [10]:receve msg:hello rabbitmq-9 [11]:receve msg:hello rabbitmq-10 [12]:receve msg:hello rabbitmq-11 [13]:receve msg:hello rabbitmq-12 [14]:receve msg:hello rabbitmq-13 [15]:receve msg:hello rabbitmq-14 [16]:receve msg:hello rabbitmq-15 [17]:receve msg:hello rabbitmq-16 [18]:receve msg:hello rabbitmq-17 [19]:receve msg:hello rabbitmq-18 [20]:receve msg:hello rabbitmq-19 [21]:receve msg:hello rabbitmq-20 [22]:receve msg:hello rabbitmq-21 [23]:receve msg:hello rabbitmq-22 [24]:receve msg:hello rabbitmq-23 [25]:receve msg:hello rabbitmq-24 [26]:receve msg:hello rabbitmq-25 [27]:receve msg:hello rabbitmq-26 [28]:receve msg:hello rabbitmq-27 [29]:receve msg:hello rabbitmq-28 [30]:receve msg:hello rabbitmq-29 [31]:receve msg:hello rabbitmq-30
MsgReceiver2 processes 19 expired messages
[1]:receve msg:hello rabbitmq-31 [2]:receve msg:hello rabbitmq-32 [3]:receve msg:hello rabbitmq-33 [4]:receve msg:hello rabbitmq-34 [5]:receve msg:hello rabbitmq-35 [6]:receve msg:hello rabbitmq-36 [7]:receve msg:hello rabbitmq-37 [8]:receve msg:hello rabbitmq-38 [9]:receve msg:hello rabbitmq-39 [10]:receve msg:hello rabbitmq-40 [11]:receve msg:hello rabbitmq-41 [12]:receve msg:hello rabbitmq-42 [13]:receve msg:hello rabbitmq-43 [14]:receve msg:hello rabbitmq-44 [15]:receve msg:hello rabbitmq-45 [16]:receve msg:hello rabbitmq-46 [17]:receve msg:hello rabbitmq-47 [18]:receve msg:hello rabbitmq-48 [19]:receve msg:hello rabbitmq-49