One, foreword
Long time no see, RabbitMQ learning update has been stalled for some time, because of various things recently interrupted the plan, but the root cause is my own thought: A bite to eat a fat man, and ultimately lead to plan every day not able to complete, in addition to learning some content these days, for an additional network engineers learn, plan may take the test, when reading a book, also participated in the exam, but only got a junior, we took advantage of the young want to go to an intermediate, energy is not allowed, capricious these days didn’t go to work overtime, Have a good reading at home, comb some knowledge, can let oneself go farther.
This period of time, continuously in hair loss, evening also suffer from insomnia, almost lasted for several months, may be because of the recent consideration is more, so feel pressure particularly big, it’s okay, through this period of time will be better, and work hard life, let oneself more vitality, come on, all like me to study hard, to write blog friends, you are the best, For dream, for youth, come on together!
This chapter will probably be the last of the basics and I will continue to learn RabbitMQ in action. I will continue to update, if you think my writing is not very bad, we can leave wechat for each other to learn together.
Where should the message go
Let’s recall now, how did we send messages before?
channel.basicPublish
Copy the code
If you still remember the above method, you are very good
We just sent the message, but we didn’t think about what to do with the message if it wasn’t reachable
Here’s an example that I used to like: [sending a package]
I fill out the paperwork, give the package to the Courier company, and the Courier delivers it to me, but if the Courier can’t find the recipient, he will mostly send the package back to me, or throw the package away (which is almost impossible, but here is just an example).
Returning to the topic, we can use two parameters when sending a message to an exchange:
- mandatory
- immediate
Mandatory parameters
Important: Mandatory is used when the specified queue cannot be found
1. When mandatory = true, the message is returned to the producer if the exchange cannot find a queue that meets the criteria based on its type and routing key
// Send a message
String msg = "hello rabbitmq";
channel.basicPublish("exchange"."".true, MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes());
System.out.println("Send a message :"+msg);
// Set the listener
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int i, String s, String s1, String s2, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
String msg = new String(bytes);
System.out.println("Message could not be delivered, now return with:"+msg); }}); channel.close(); connection.close();Copy the code
- We use basicPublish to send messages
// The first parameter is the switch name
// The second parameter is rountingkey
// The third parameter is mandatory, set to true, to return the message to the producer if no queue is found
// Other parameters are omitted
channel.basicPublish("exchange"."".true, MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes());
Copy the code
- So, how should we receive the returned message? Then we need to add a return listener
// Register a return listener to receive returned messages
channel.addReturnListener(new ReturnListener() {
@Override
public void handleReturn(int i, String s, String s1, String s2, AMQP.BasicProperties basicProperties, byte[] bytes) throws IOException {
// Get the message and convert it to a string
String msg = new String(bytes);
System.out.println("Message could not be delivered, now return with:"+msg); }});Copy the code
- The results of
Send message: Hello rabbitmq could not send message, now return: Hello RabbitMQCopy the code
2. When mandatory = false, the message is discarded
- When we set Mandatory to false, no messages will be returned regardless of whether we define return listeners
// The third parameter is mandatory
channel.basicPublish("exchange"."".false, MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes());
Copy the code
- The results of
Send message: Hello RabbitMQCopy the code
The immediate parameter
Important: This parameter is mainly for whether there are consumers and queue bindings
If immediate = true, the message is queued if there is no consumer on the queue when the switch routes the message. Another important point is that basic. Return is returned to the consumer if there is no consumer on all queues that match the routing key
It is similar to Mandatory in that the message is returned to the producer, except that immediate determines whether the message needs to be returned to the producer based on whether consumers are listening on the queue
We won’t go into the basics of immediate usage here, because RabbitMQ 3.0 has removed support for IMMEDIATE in favor of TTL and DLX
3. Backup switch
A backup switch, also known as AE, is also known as ** “standby switch” ** because only messages that are not routed are stored
To declare AE, simply configure alternate-exchange
// Parameter configuration
Map<String,Object> params = new HashMap<>();
// Set the name of the backup switch. The second parameter must be the same as the name of the backup switch created by exchangeDeclare
params.put("alternate-exchange"."AEExchange");
// Create a normal switch and specify parameters for the backup switch
channel.exchangeDeclare("normalExchange"."direct".true.false,params);
// Backup switch
channel.exchangeDeclare("AEExchange"."fanout".true.false.null);
// A normal queue, which holds messages that can be routed correctly
channel.queueDeclare("normalQueue".true.false.false.null);
channel.queueBind("normalQueue"."normalExchange"."normalKey");
// A backup queue for storing messages that cannot be routed
channel.queueDeclare("AEQueue".true.false.false.null);
channel.queueBind("AEQueue"."AEExchange"."");
channel.basicPublish("normalExchange"."normalKey",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());
Copy the code
- In the example above, because we specified an existing routing key, messages can be routed to the normalQueue via normalExchange
channel.basicPublish("normalExchange"."normalKey",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());
Copy the code
We can see that messages are successfully routed to normalQueue
- Let’s change the RoutingKey to one that doesn’t exist to see if it gets routed to the backup switch
channel.basicPublish("normalExchange"."",MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());
Copy the code
Since we set up a routing key that does not exist, it will be routed to the backup switch and queue
Now you can start RabbitMQ and open IDEA to test
The last point about backup switches, special cases:
- If the backup switch does not exist, neither the client nor the RabbitMQ server is abnormal and messages are lost
- If the backup switch is not bound to any queues, no exceptions will occur and messages will be lost
- If the backup switch does not have any matching queues, no exceptions will occur and messages will be lost
- If the backup switch is used with the MANDATORY parameter, the mandatory parameter is invalid
Iv. Expiration Time (TTL)
TTL means Time to Live Expiration Time
There are two ways to set the expiration time:
- Set expiration time for messages
- Set an expiration time for the queue
4.1 Setting the Message Expiration Time
There are also two ways to set the message expiration time;
- 1. By setting the queue properties, all messages in the queue have the same expiration time
// Create a switch
channel.exchangeDeclare("ttlExchange"."direct".true.false.false.null);
// Create an expiration time through the queue attribute
Map<String,Object> params = new HashMap<>();
// The expiration time is 5 seconds
params.put("x-message-ttl".5000);
// Create a queue
// Set parameters
channel.queueDeclare(QUEUE_NAME,false.false.false,params);
channel.queueBind(QUEUE_NAME,"ttlExchange"."ttlKey");
// Send a message
String message = "hello rabbitmq";
channel.basicPublish("ttlExchange"."ttlKey".null,message.getBytes());
System.out.println("Send a message :"+message);
Copy the code
We can see that in the queue below, there is already a message and there is a TTL identifier
We’ll check back in five seconds
The message no longer exists, or it has reached its expiration date and is discarded
-
If the TTL is not set, the message will not expire
-
If the TTL is set to 0, the message will be discarded immediately unless it can be delivered directly to the consumer
-
2. Set the message expiration time separately
We have a requirement that different messages have different expiration times. For example, we want orders to be discarded if payment is not completed in 30 minutes, and we want users to automatically receive goods if they do not receive goods in 7 days. Then we need to set expiration times separately for each message
// Set parameters
AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
// Messages will expire in 5 seconds
builder.expiration("5000");
AMQP.BasicProperties properties = builder.build();
String message = "hello rabbitmq";
// The third parameter is the configuration above
channel.basicPublish("ttlExchange"."ttlKey",properties,message.getBytes());
System.out.println("Send a message :"+message);
Copy the code
We can see that there is now a message stored in the queue
5 seconds later, we look again, the message expired
4.2 Setting the TTL of the Queue
Queue expiration: There are no consumers, the queue is not redeclared, and basic.get is not called during the expiration period
We set the queue expiration time, mainly through the X-Expires attribute
// Set the properties
Map<String,Object> params = new HashMap<>();
params.put("x-expires".10000);
// Create a queue
// The fifth attribute is configured for the above
channel.queueDeclare(QUEUE_NAME,false.false.false,params);
Copy the code
We can see that the queue has been created successfully
The queue expires after 10 seconds
5. Dead-letter queues
Dead letter queue, or DLX
If a message becomes dead letter in a queue, it is resend to another switch. This queue is called a dead letter queue
We need to think about the conditions that become dead-letter:
- The message is rejected (basic.reject/basic.nack) and the Requeue parameter is set to true
- Message expiration
- The queue length reaches the maximum. Procedure
The dead-letter queue can be used for order services. The user places an order but does not pay for it. After 30 minutes, the order will be sent to DLX, and the consumer only needs to listen to the DLX queue to get the overdue order and restore the inventory of the goods
X -dead-letter-exchange must be configured for the dead letter queue
// Create a dead-letter switch
channel.exchangeDeclare("exchange.dlx"."direct".true);
// Create a normal switch
channel.exchangeDeclare("exchange.normal"."fanout".true);
// Configuration information
Map<String,Object> params = new HashMap<>();
params.put("x-message-ttl".5000); // Message expiration time
params.put("x-dead-letter-exchange"."exchange.dlx"); // Specify a dead-letter switch
params.put("x-dead-letter-routing-key"."dlxKey"); // Specifies the routing key of the dead letter queue
Create a dead letter queue
channel.queueDeclare("queue.dlx".true.false.false.null);
// Create a normal queue and tell the queue to resend the message to the exchange.dlx switch if it expires
channel.queueDeclare("queue.normal".true.false.false,params);
// Bind the switch
channel.queueBind("queue.normal"."exchange.normal"."");
channel.queueBind("queue.dlx"."exchange.dlx"."dlxKey");
// Send a message
channel.basicPublish("exchange.normal"."", MessageProperties.PERSISTENT_TEXT_PLAIN,"hello rabbitmq".getBytes());
Copy the code
We run the program and create two queues
Five seconds later, the message is resend to the dead-letter queue
Hang in there a little bit longer, I’m just going to wrap it up, but let’s move on to the last point
Delay queue
What is a delay queue?
When a message is sent, it is not immediately available to the consumer, but wait a certain amount of time before the consumer can consume it
His example is the same as the one above, but it is basically a combination of DLX and TTL, which we talked about in the last section
I’ve been looking at Springboot’s RabbitMQ integration for the past two days. It’s easy to use as long as you understand the basics. No matter how it’s packaged, it’s just more efficient. But you can’t get away from the basics.
Tonight, I’m going to get a good night’s sleep and start writing something else tomorrow. Good night, guys!