Hello everyone, I’m Xiao CAI. A man who wants to be a man who talks architecture! If you also want to be the person I want to be, or point a concern to do a companion, let small dishes no longer lonely!
This article focuses on the common problems with RabbitMQ
Refer to it if necessary
If it is helpful, do not forget the Sunday
Wechat public number has been opened, xiao CAI Liang, did not pay attention to the students remember to pay attention to oh!
- Message reliability Problem: How do I ensure that sent messages are consumed at least once?
- Delayed message problem: How to implement delayed message delivery?
- Message accumulation problem: How to solve the problem of millions of messages piled up and unable to timely consume?
We have already explained how to solve the problem of message loss, that is, to ensure the reliability of the message, so the other two problems are also important, this article will talk about the solution of the other two problems ~!
Message loss solution: “the RabbitMQ | message loss is the way it is
Delayed messages
Delaying the message literally means delaying the receipt of a message, so how can you delay the arrival of a message? This is what we need to think about, and there are two concepts in RabbitMQ that we need to understand before we look at delay queues
- Dead-letter exchange
- TTL
1) Dead-letter switch
A “dead letter” is the abandonment of a message that has died. Under what circumstances can an ordinary message become a “dead letter”? The following three conditions must be met:
- Consumer use
basic.reject
或basic.nack
Declare a consumption failure and set the Requeue parameter of the message tofalse
- The message is an expired message that has not been consumed
- When the queue of messages to be delivered fills up, the earliest messages become dead letters
The dead letter switch is where the dead letter belongs.
If a queue is configured with dead-letter-exchange and a switch is specified, the dead letter from the queue will be delivered to the switch, which is called dead-letter exchange (DLX).
Steps: When a producer sends a message to a queue (siml. queue), if a consumer consumes a message from the queue (reject), and the queue is bound to a dead-letter switch (DL-queue), Dead-letter messages will then be sent to the dead-letter queue.
From the normal queue -> dead-letter queue process, we must declare two key pieces of information
- The name of the dead-letter switch
- Dead-letter Routing key bound to a dead-letter queue on a switch
These two pieces of information are also the basic configuration for delivering messages.
Let’s briefly simulate the scenario for condition 1
1. First declare a dead letter switch and a dead letter queue
We use simple annotations to generate it directly
On the RabbitMQ console interface, you can see that it has been successfully generated
2. Declare normal use of switches and queues
At this point we can create a working switch and queue and specify the dead letter switch
You can also view the creation status from the console
We can determine whether there is a declared dead letter switch by the DLX and DLK flags of the queue
3. Simulated rejection
Then we now simulate the client rejecting the message in code
1) Message sending
2) Message reception
View the console and the result is as follows:
2021-11-06 23:56:52.095 INFO 2112 --- [ntContainer#0-1Switch |] C.L.M.C.L istener. SpringRabbitListener: normal business receives the message: [hello!]2021-11-06 23:56:52.118 INFO 2112 --- [ntContainer#1-1] C.L.M.C.L istener. SpringRabbitListener: | dead-letter switch receives the message: helloCopy the code
This shows that our dead-letter switch has been successfully functioning
2) the TTL
We have successfully seen the use of dead letter switches, but this does not seem To have much To do with the delay queue we started with, let alone the TTL(time-to-live) which is used To handle delayed messages!
In the concept of TTL, if a message in a queue is not consumed after the TTL ends, the message will automatically become dead letter, and there are two kinds of TTL timeout cases:
- The queue where the message resides has a lifetime set
- The message itself sets the lifetime
We also perform the simulation scenario of condition 2 above
1. Declare dead letter switches and dead letter queues (completed above)
2. Declare a delay queue and specify a dead-letter switch
Again, the console looks at the creation result, and we see not only DLX and DLK flags, but also a TTL, indicating that the queue is deferred
3. Simulate consumption timeout
We send a message to the delay queue, and no consumer consumes it. We wait 1 minute to see if we can get into the dead letter queue
We have sent a message to the delay queue and a minute later we have also successfully discovered on the console that this message has entered the dead letter switch
2021-11-07 00:01:30.854 INFO 32752 --- [ntContainer#1-1] C.L.M.C.L istener. SpringRabbitListener: | dead-letter switch receives the message: the test TTL - the messageCopy the code
If both the message and the queue have a timeout, the shortest TTL is used. The message timeout is as follows:
As shown in the figure above, we can use the Message class to transmit Message information and set the timeout time. We set the timeout time to 5000 ms. After sending the Message successfully, the console also successfully prints the Message consumed by the dead letter switch after 5000 ms:
2021-11-07 00:03:09.048 INFO 39996 --- [ntContainer#1-1] C.L.M.C.L istener. SpringRabbitListener: | dead-letter switch receives the message:this is a ttl message
Copy the code
3) Delay queue
We used the dead letter switch to implement the delay queue indirectly, but RabbitMQ doesn’t have to be so troublesome, RabbitMQ already packages the plugin for us, we just need to download and install it
RabbitMQ plug-in download address
When we enter the address, we can find many plug-ins. Search the keyword delay to find the plug-ins we need for download
RabbitMQ plugins: RabbitMQ plugins: RabbitMQ plugins: RabbitMQ plugins: RabbitMQ plugins: RabbitMQ plugins: RabbitMQ plugins
docker run -itd --name rabbitmq -v plugins:/plugins -p 15672:15672 -p 5672:5672 rabbitmq:management
Copy the code
So I just upload the plugin to the plugins directory in the container
Then enter the container and run the following command to open the plug-in
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
Copy the code
And we can see that there is an option for type type when we create the switch in the console
This step will indicate that RabbitMQ delay queuing is enabled
Then we can use DelayExchange, first we need to understand the code to create a delay switch:
Method 1
Way 2
We can send messages when we have everything ready
When sending a message, the message header must contain the X-delay parameter, which specifies the delay time
After this configuration, we can see on the console that delay.queue receives the corresponding message after 10 seconds and is then consumed by the corresponding consumer
3) summary
From dead letter switches to TTL to delay queues, we’ve looked at how to implement delayed messages step by step. Then we’ll conclude with a little bit:
Question 1: What kind of news becomes a dead letter?
- The message is rejected by the consumer or returned to NACK
- The message timed out and was not consumed in time
- The message queue is full
Problem 2: The way the message timed out
- Set the TTL attribute for the queue
- Set the TTL attribute for the message
Question 3: How do I use delay queues
- Download and enable the RabbitMQ delay queue plug-in
- Declare a switch and set the delayed property to true
- When sending a message, add the X-delay header with the value of timeout
Problem 4: Use scenario of delay queues
- Delay sending SMS notification
- Automatic order cancellation
- Inventory automatically rolls back
Lazy queues
With delay queues out of the way, let’s move on to lazy queues
Before we talk about lazy queues, let’s throw out a question
How does RabbitMQ solve the message heap problem
When does message accumulation problem occur?
- When producers are producing much faster than consumers are consuming
- When the customer is down, it does not restart in time
So how to solve this problem? The general idea is as follows:
- After the consumer machine restarts, add more consumers for processing
- Create a thread pool inside the consumer processing logic to improve the processing speed by using multiple threads
- Expand the capacity of queues and increase the upper limit of stacking
These methods are theoretically fine, but they are not elegant or even flexible. Instead, we can use the lazy queue type that comes with RabbitMQ
What is an lazy queue? Let’s take a look at some of the features of lazy queues:
- When received, the message is stored directly to disk instead of memory
- The message is read from disk and loaded into memory before it is consumed by the consumer
- It supports the storage of millions of messages
The bottom line is to take advantage of disk buffering. The downside of this mechanism is that messages are less time-sensitive and performance is limited by disk I/O. With that in mind, how can we create lazy queues
Method 1
Way 2
Methods 3
This is to change a running queue to an inert queue based on command line modifications directly
rabbitmqctl set_policy Lazy "^lazy-queue$" '{"queue-mode":"lazy"}' --apply-to queues
Copy the code
The meanings of several command parameters are as follows:
- Rabbitmqctl: command line tool
- Set_policy: Adds a policy
- Lazy: indicates the policy name, which can be customized
- ^lazy-queue$: Matches the queue name with a regular expression
- ‘{“queue-mode”:”lazy”}’ : sets the queue to the lazy mode
- — Apply-to queues: Policies that act on queues
While this lazy queuing approach has the disadvantage of reducing message timeliness, it is not unacceptable in some scenarios, and its advantages are equally obvious:
- Disk-based storage, high message upper limit
- No intermittent page-out, stable performance
So far we have covered the common problems with RabbitMQ, which we might not encounter in a normal development scenario, but we still need to be aware of them before they happen!
Don’t talk, don’t be lazy, and xiao CAI do a blowing bull X do architecture of the program ape ~ point a concern to do a companion, let xiao CAI no longer lonely. See you later!
Today you work harder, tomorrow you will be able to say less words!
I am xiao CAI, a man who grows stronger with you. 💋
Wechat public number has been opened, xiao CAI Liang, did not pay attention to the students remember to pay attention to oh!