preface
With the continuous expansion of project business, message queue has become a very important role in the project in the comprehensive microservitization environment. If you’re not sure why you’re introducing message queues. So you can read why message queues? . As a RabbitMQ fan, this article explains the basics of common RabbitMQ interview questions.
Introduction of the RabbitMQ
RabbitMQ is one of the most popular open source messaging middleware. It is based on the Erlang language, supports multiple messaging protocols, has very low message latency, high concurrency and high performance, and provides Client apis for almost all languages. It also has a rich Web management interface. Why use message queues? This article has listed the advantages and disadvantages of several open source messaging middleware. With a slightly lower throughput (though sufficient for most small and medium businesses), it is a relatively good messaging middleware that is widely used by small and medium businesses.
The RabbitMQ architecture diagram
To understand how RabbitMQ sends and consumes messages, the producer establishes a TCP Connection to the RabbitMQ server. If you don’t understand IO multiplexing read the Redis thread model – how to understand IO multiplexing? The RabbitMQ server will channel messages to the RabbitMQ server, which will forward the messages internally through the switch. The final queue of the messages is determined by a Binding, which represents a Binding between the switch and the queue, so that the different switches can match the corresponding queue. The switch and queue are separated by a Virtual Host, which can be interpreted as MySQL and the different databases in MySQL. Consumers and producers alike need to establish a Connection to the RabbitMQ server and communicate internally through channels, subscribing to different queues to consume messages.
RabbitMQ working mode
Publish/Subscribe Publish Subscribe
The publish-subscribe pattern is the popular broadcast type used to send messages to all queues bound to it
Publication and subscription mode is widely used in development. For example, when an order is placed successfully in e-commerce business, a message of order creation needs to be broadcast. Inventory, coupon, merchant and other systems need to subscribe to this message to process downstream business.
Work Queues compete for consumption
Think about a production environment where a microservice is typically a cluster of multiple instances. We want to ensure that multiple instances of a microservice can consume messages only once, otherwise repeated consumption will occur. As shown above: assuming C1 and C2 are two instances of an inventory system, the two instances of an inventory system can only consume a message once. Simply, as long as two microservices are listening to the same queue, only one of them can be consumed successfully. RabbitMQ has done this for us, and for this reason RabbitMQ does not support queue level broadcasting, but switch level broadcasting.
RoutingKey RoutingKey match
Switches and queues are bound together as a Binding object through routing keys. The switch sends messages to all queues that match its RoutingKey. Some places may separate BingdingKey from Routingkey, but both are understood as routingkeys by the official client dependencies and by the SpirngBoot dependencies. If you have to separate, you can understand that. The BingdingKey is required to bind the switch to the queue, and the RoutingKey is required to forward messages to the switch. When the RoutingKey matches the BindingKey, the message is correctly sent to the queue.
In the figure above, the switch binds two queues using the routing key KEY1. When the switch sends a message, both queues receive the message if the routing key key1 is specified. If key2 or key3 is specified as the routing key, only the following queues can receive messages. This routing matching pattern can be used in real business scenarios, where we can send a message and expect multiple systems to consume it, or send multiple messages and expect only one of them to consume it.
Topics Wildcard match
This works almost the same as Routing key matching, except that topics can use wildcard “*” and “#” to blur Routing key matching. * can replace exactly one word; “#” can replace exactly zero or more words. It provides high scalability for routing key matching.
Message persistence
Since RabbitMQ is a third-party service independent of the two systems, one of the things we have to consider is what happens when the RabbitMQ service goes down? To solve the problem of memory queue messages being lost after RabbitMQ restarts, RabbitMQ provides persistence.
Note that both the queue and the message must be set to persist. If the queue is set to persist separately, the message is not persisted. After the restart, the queue is still there, but the message is not. Set message persistence separately, do not set queue persistence, after the restart of the queue is gone, so is the message.
However, enabling persistence means a performance penalty for RabbitMQ, as persistent messages are written to disk files, so whether all messages and queues are persistent is a tradeoff in a real world scenario.
TTL message expiration setting
TTL Full name Time To Live: Indicates the TTL. RabbitMQ can set the lifetime for either the entire message queue or for a single message. If both are set, the smaller time will prevail.
Set the message lifetime for the entire queue. Set the TTL in milliseconds while building the queue. All messages sent to the queue will expire after a specified time.
It is important to note that when a message is set to expire, the message does not necessarily disappear after the set time, but is lazily deleted. Messages are not expired until they are at the top of the queue and are about to be consumed, similar to the lazy deletion of key expiration strategies of Redis. Otherwise, a schedule must be enabled to cycle messages in the queue every certain time to determine whether they are expired, which is very inefficient.
RabbitMQ dead letter queue
A Dead Letter queue is called a Dead Letter Exchange or DLX in RabbitMQ, but is actually a short name for a Dead Letter Exchange and a Dead Letter queue. If we bind the normal queue to a dead letter switch, then the message will not be discarded when it becomes dead letter, but will be sent to the dead letter switch and then routed to the queue bound to the dead letter switch.
A dead letter switch and a dead letter queue are not a special component; they are declared just like normal switches and queues. To use it, just set its property parameter x-dead-letter-exchange.
As shown in the figure above, if the queue is bound to a dead letter switch, messages that become dead letters are not discarded, but are routed to the dead letter switch and routed to the corresponding queue. So how does a message become a dead letter? There are usually three cases
- Queue message reach length limit. RabbitMQ can set the queue length to 10, for example, and when the queue is full of 10 messages and the next message reaches the maximum length, it will become dead letter
- The consumer refuses to sign for the message and does not re-queue, Requeue = false
- The message was not consumed over the lifetime
RabbitMQ delays messages
Delayed messages are widely used in businesses. For example, an order is closed if the user does not pay within 30 minutes of placing an order. Business scenarios such as automatic confirmation of receipt of goods if the goods are not received within 15 days after delivery. RabbitMQ can delay sending messages by setting message lifetime + dead letter queue.
As shown in the figure above, we can send a message to a Queue that has no consumer subscription, give the Queue and the message a lifetime of 30 minutes, after 30 minutes the message expires and becomes a dead-letter message, it reaches the dead-letter switch DLX and then routes to the dead-letter Queue, where the consumer subscribes and consumes it. This enables the delayed message function!