Introduction to the

Message Queue Middleware (MQ) is a platform independent data exchange based on efficient and reliable Message passing mechanism, and integrates distributed systems based on data communication. By providing a message passing and message queuing model, it can extend interprocess communication in a distributed environment.

At present, there are many open source message middleware, and the mainstream ones include RabbitMQ, Kafka, ActiveMQ, RocketMQ, etc. Message-oriented middleware provides a mechanism for integrating applications in a flexible, loosely coupled way.

Messaging middleware is suitable for distributed environments where reliable data transfer is required. In the system of message-oriented middleware, different objects transmit messages to each other to activate each other’s events to complete the corresponding operations. Message-oriented middleware is often used to shield the characteristics between various platforms and protocols and realize the collaboration between applications. Its advantage is that it can provide synchronous and asynchronous connection between the client and the server, and it can send or store and forward messages at any time.

The use of message-oriented middleware can be summarized as follows:

  • The decoupling
  • redundant
  • Peak clipping
  • recoverability
  • In order to ensure
  • The buffer
  • Asynchronous communication

RabbitMQ is a Message middleware that implements AMQP (Advanced Message Queuing Protocol) in Erlang language. It has excellent performance in ease of use, extensibility, reliability and high availability.

The installation

While installing RabbitMQ manually is cumbersome, here is a simple Docker-based installation:

docker run -d --name rabbitmq --hostname my-rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin [RabbitMQ image ID pulled]

The core concept

RabbitMQ as a whole is a producer-consumer model that is responsible for receiving, storing, and forwarding messages. In computer terms, the RabbitMQ model is more like a switch model. The overall model architecture of RabbitMQ is shown in the figure below:

-Rufus: Well, the producers.

The producer creates the message and publishes it to RabbitMQ. A message can typically contain two parts: the body of the message and the label. In practice, the message body is typically a piece of data with a business logic structure, such as a JSON string. The label of the message is used to describe the message, such as the name of a switch and a route key. The producer passes the message to RabbitMQ, which then sends the message to the interested Consumer based on the tag.

-Rufus: You’re a Consumer.

The consumer connects to the RabbitMQ server and subscribes to the queue. During message routing, the label of the message is discarded, the message placed in the queue is only the message body, and the consumer is only consumed to the message body.

Broker: Service node

For RabbitMQ, a RabbitMQ Broker can be viewed simply as a RabbitMQ service node, or as a RabbitMQ service instance. In most cases, a RabbitMQ Broker can also be thought of as a RabbitMQ server.

The Queue, Queue

The producer of RabbitMQ produces messages and eventually delivers them to a queue, from which consumers can retrieve messages and consume them. Multiple consumers can subscribe to the same queue, and messages in the queue are by default distributed evenly (round-robin) among multiple consumers, rather than each consumer receiving all messages and processing them. RabbitMQ does not support queue-level broadcast consumption.

It’s an Exchange

Instead of sending a message directly to a queue, a producer sends a message to a exchange, which routes the message to one or more queues. If the route is not available, it is returned to the producer depending on the configuration or simply discarded. There are four types of switches, and different types have different routing strategies.

BindingKey: The key to bind to

RabbitMQ uses bindings to associate a switch with a queue. During binding, a binding key is typically specified so that RabbitMQ knows how to route messages to the queue properly.

RoutingKey: Routing key

When a producer sends a message to a switch, it typically specifies a RoutingKey, which specifies the routing rules for the message. This RoutingKey needs to be used in conjunction with the switch type and binding key in order to be effective. The switch matches the routing key and the binding key according to its type, and forwards the message to the corresponding queue if the match is successful.

Connection: the Connection

Both producers and consumers need to establish a TCP Connection with the RabbitMQ Broker. This Connection is called a Connection.

Channel: the Channel

Once the TCP connection is established, the client can create an AMQP channel, each of which is assigned a unique ID. A channel is a virtual Connection over a Connection. Each AMQP instruction that RabbitMQ processes is done over a channel.

Note: in multi-threaded application scenarios, each thread corresponds to one channel, reuse the same connection, which can improve performance, but also easy to manage.

Switch type

RabbitMQ uses four types of switches: fanout, direct, topic, and headers.

fanout

A FANOUT switch routes all messages sent to the switch to all queues bound to the switch, masking the routing and binding keys.

direct

Direct type exchanges route messages to queues where bindingkeys and routingkeys match exactly.

topic

A Topic exchange extends the matching rules. It is similar to a Direct exchange in that it routes messages to a queue where bindingKey and routingKey are matched, but the matching rules are somewhat different. It has the following conventions:

  • RoutingKey as a dot “.” A delimited string, such as “com.rabbitmq.client”.
  • A BindingKey is also a dot, as is a RoutingKey. A delimited string.
  • BindingKey can contain two special strings, * and #, for fuzzy matching. # is used to match one word and # is used to match one or more words (which can be zero).

headers

Switches of type HEADERS do not rely on matching rules for routing keys to route messages, but instead match based on the HEADERS property in the content of the message being sent. When a message is sent to a switch, RabbitMQ will get the headers of the message and compare whether the key-value pairs match the queue and the key-value pairs specified when the switch is bound. If so, the message will be routed to the queue. Otherwise, the message will not be routed to the queue. The HEADERS type of switch is very poor and impractical, and is almost never seen to exist.

Operation process

Now let’s summarize the entire RabbitMQ usage process. The first is the producer:

  1. The producer connects to the RabbitMQ Broker, establishes a connection, and opens a channel.
  2. The producer declares a switch and sets related attributes, such as switch type, persistence, and so on.
  3. A producer declares a queue and sets related properties, such as exclusion, persistence, auto-delete, and so on.
  4. The producer binds the switch to the queue via the route key.
  5. The producer sends a message to the RabbitMQ Broker, which contains routing keys, switches, and so on.
  6. The corresponding switch looks for a matching queue based on the route key it receives.
  7. If found, the message sent from the producer is put into the appropriate queue.
  8. If it is not found, the option to discard or fall back to the producer is based on the properties configured by the producer.
  9. Close the channel.
  10. Close the connection.

For consumers:

  1. The consumer connects to the RabbitMQ Broker, establishes a connection, and opens a channel.
  2. The consumer requests the RabbitMQ Broker to consume messages in the queue (push mode), may set the appropriate callback function, and may do some preparatory work.
  3. Wait for the RabbitMQ Broker to respond and deliver the message in the appropriate queue, and the consumer receives the message.
  4. Consumer Acknowledgement (ACK) of messages received.
  5. RabbitMQ deletes the corresponding acknowledged message from the queue.
  6. Close the channel.
  7. Close the connection.