[RabbitMQ series that can be understood by laymen] - RabbitMQ quick introduction (including rich examples)

preface

Congratulations to all the friends who read this article for successfully unlocking the quick start content of RabbitMQ series 🎁 Through this article, you will quickly learn what middleware is? What is rabbit MQ? How does RabbitMQ work? Finally, Xiaoming will take you through an example to deepen your impression of RabbitMQ 😁 The article is a little long. Please be patient 😄

If you have fewer question marks, you can skip the first four titles and start reading from the fifth title

1, What is middleware

I don't know if I feel dizzy when I see the overwhelming definition like a nickname, so I checked the nickname on the Internet and found that many people have the same question: "What is middleware exactly?"

The nickname saw an easy to understand example on stack overflow:

The phrase whose nickname is enclosed in a red box is translated as follows:

"You will notice that this is basically the same as the definition of the operating system. Therefore, for example, TCP/IP protocol stack or cache can be regarded as middleware. But your operating system can also provide the same function. In fact, middleware can be regarded as a special extension of the operating system for a group of applications that depend on it. It only provides a higher level "Service for the second time."

The understanding of the nickname is to regard middleware as a rule, or middleware is a porter who abides by TCP/IP protocol.

The three basic middleware are: transaction middleware, message middleware and application server middleware

2, What is message oriented middleware

With a soul question, Xiaoming went online to search for "what is message oriented middleware?" I found that the following reply is easy to understand:

The phrase whose nickname is enclosed in a red box is translated as follows:

"Message broker - any system that processes messages (in MOM) or, more accurately, routes messages to specific consumers / recipients. Message brokers are usually based on MOM. MOM provides basic communication between applications and things like message persistence and guaranteed delivery. "Message broker is an integral part of message oriented middleware."

In short, build a reliable information transmission bridge between "producer" (message sender) and "consumer" (message receiver)

3, What is MQ

Above, we mentioned the concept of "message middleware". In the screenshot, we also mentioned "Rabbitmq - a message broker; a MOM implementation; an open source implementation of AMQP". Next, let's understand what MQ is:

The full name of MQ is Message Queue. Message Queue is the communication method of "a series of functions such as low coupling, reliable delivery, broadcasting, flow control and final consistency" between applications.

4, Why MQ

1. System decoupling: for example, our original demand is to send emails and messages in the system to course buyers, but the demand changes suddenly. We think that the teacher should also receive a reminder of the beginning of the course. In fact, the main content of the message is the same, but the text of the prompt is different. If we solve it with code, we need to write an interface and define something to tell the app side, However, if we send a message through MQ, we don't need to add a new interface, push the message to the teacher side of the app, and the app can modify the copy.
2. Asynchronous call: for example, a person wants to register as a teacher, but the background needs to do some similar queries to check whether he is qualified in the database and whether he is a user in the blacklist. After completing these, he starts to insert a piece of teacher data for him, and there may be some relationship data to be created. Finally, he sends a message to remind the user that the registration is successful, which is too slow, In fact, we can insert the data into mq and send a message to the user after confirming that he can register as a teacher and before inserting into the database, so that the teacher can do some follow-up operations similar to creating a course after receiving the notice
3. Traffic peak shaving: for example, the spike scenario far exceeds the upper limit of the processing capacity of the server at ordinary times. Assuming that 1000 pieces of data can be processed at ordinary times, 100000 pieces of data are suddenly poured into the server in a very short time, which is likely to bring the server down. If you block a layer of MQ in front of the server, MQ can delay the request and reduce the pressure on the server without downtime.

5, Four keywords in MQ

  • Producer: the initiator of a business, which creates a message and sends it to a message server (Broker)
  • Consumer: the processor of the business, which obtains messages from the message server (Broker) and performs subsequent business logic processing
  • Exchange: bind the message to the corresponding queue according to the routing key
  • Queue: saves messages and forwards them to consumers

6, What is AMQP

AMQP (Advanced Message Queuing Protocol) is a reliable and universal network protocol for asynchronous message transmission between processes. It is similar to SMTP, HTTP, FTP and other protocols. It is a protocol specially used for unified message service. It is designed for message middleware and is not limited by development language.

7, How RabbitMQ works

  1. Producer: Message producer, which delivers messages.
  2. Connection: each time you visit RabbitMQ, a connection is established to connect publisher, consumer and broker
  3. Channel: the logical Connection established by the channel inside the Connection. If the application supports multithreading, each thread usually creates a separate channel for communication, and the channels are completely isolated (as a lightweight Connection, the channel greatly reduces the overhead of the operating system in establishing TCP connection)
  4. Broker: an application that receives and distributes messages.
  5. Exchange: message arrives at the first stop of the broker, matches the routing key in the query table according to the distribution rules, and distributes the message to the queue. Common types are: direct (point-to-point), topic (publish subscribe) and fan out (multicast).

8, RabbitMQ three important Exchange modes

  1. Fanout mode
    Official introduction:
    Publish/Subscribe: Sending messages to many consumers at once.

    Fanout - publish and subscribe mode is a broadcast mechanism. It is a mode without routing key. As long as the queue is bound to the switch, the messages received by the switch will be forwarded to all queues bound to the switch. Therefore, the fanout switch is the fastest to forward messages.

  2. Direct mode
    Official introduction:
    Routing: Receiving messages selectively

    Direct routing mode is based on the superposition of fanout mode and adds routing routingKey, that is, all messages sent to Direct Exchange will be forwarded to the Queue specified in the routingKey. Therefore, during message delivery, it should be noted that the routingKey must be completely matched before being received by the Queue, otherwise the message will be discarded.

  3. Topics mode
    Official introduction:
    Topics: Receiving messages based on a pattern (topics)

    Topic mode is a superposition based on direct mode and adds fuzzy routing key, that is, wildcards can be used for fuzzy matching.
    ×××.# : Match 0 or 1 or more levels
    ×××.* : There can only be 1 level matching
    There are no partners who understand the use of this wildcard. Please continue to look down at "Xi. Detailed explanation of RabbitMQ management interface"

9, Message producer

  1. Create the project as shown in the figure below

  2. In POM Introducing dependencies into XML

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. In application YML for configuration
# Service port
server:
  port: 9000
# Configure rabbitmq service
spring:
  rabbitmq:
    host: Yours rabbitmq Public network address
    port: 5672
    username: user name
   password: password
   publisher-confirms: true
   publisher-returns: true
  1. Define producer
  • Order.java
public class Order {
    private String orderId;
    private Long uid;
    private String name;

    public Order() {

    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public Order(String orderId, Long uid, String name) {
        this.orderId = orderId;
        this.uid = uid;
        this.name = name;
    }

    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • OrderService.java
@Component
public class OrderService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void makeOrderFanout(Long userId, Long productId, int num) {
        // 1. Simulated user orders
        String orderNumer = UUID.randomUUID().toString();

        // 2. After placing the order
        System.out.println("user " + userId + ",The order number is:" + orderNumer);

        // 3. Complete message distribution through MQ
        //Parameter 1: switch; Parameter 2: route Key/queue queue name; Parameter 3: message content
        String exchangeName = "fanout_order_exchange";
        String routeKey = "";

        // Send order information to RabbitMQ 
        rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
    }

    public void makeOrderDirect(Long userId, Long productId, int num) {
        // 1. Simulated user orders
        String orderNumer = UUID.randomUUID().toString();

        // 2. After placing the order
        System.out.println("user " + userId + ",The order number is:" + orderNumer);

        // 3. Complete message distribution through MQ
        //Parameter 1: switch; Parameter 2: route Key/queue queue name; Parameter 3: message content
        String exchangeName = "direct_order_exchange";
        String routeKey1 = "email";
        String routeKey2 = "sms";

        // Send order information to RabbitMQ
        rabbitTemplate.convertAndSend(exchangeName, routeKey1, orderNumer);
        rabbitTemplate.convertAndSend(exchangeName, routeKey2, orderNumer);
    }

    public void makeOrderTopic(Long userId, Long productId, int num) {
        // 1. Simulated user orders
        String orderNumer = UUID.randomUUID().toString();

        // 2. After placing the order
        System.out.println("user " + userId + ",The order number is:" + orderNumer);

        // 3. Complete message distribution through MQ
        //Parameter 1: switch; Parameter 2: route Key/queue queue name; Parameter 3: message content
        String exchangeName = "topic_order_exchange";
        String routeKey = "sms.email.duanxin";

        // Send order information to RabbitMQ topic
        rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer);
    }
 }   

Of which:

public void convertAndSend(String exchange, String routingKey, Object object) throws AmqpException {
    this.convertAndSend(exchange, routingKey, object, (CorrelationData)null);
}

Specify the switch, routing Key and message body to be sent through the convertAndSend method. Of course, there is no need to set the routing Key in the fanout mode.

  1. Write test class
  • ProducerApplicationTests.java
@SpringBootTest
class ProducerApplicationTests {
    @Autowired
    private OrderService orderService;

    @Test
    void contextLoads() {
        orderService.makeOrderFanout(1l, 1l, 12);
    }

    @Test
    void directTest() {
        orderService.makeOrderDirect(1l, 1l, 12);
    }

    @Test
    void topicTest() {
        orderService.makeOrderTopic(1l, 1l, 12);
    }
 }   

10, Message consumer

  1. Create the project as shown in the figure below

  2. In POM Introducing dependencies into XML

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. In application YML for configuration
# Service port
server:
  port: 9001
# Configure rabbitmq service
spring:
  rabbitmq:
    host: Yours rabbitmq Public network address
    port: 5672
    username: user name
   password: password
   publisher-confirms: true
   publisher-returns: true
  1. Write code related to binding relationship
    Note: the small name defines the fixed relationship in the consumer, which can avoid the consumer's running error
10.4.1.Direct mode:

DirectRabbitMqConfiguration.java

@Configuration
public class DirectRabbitMqConfiguration {
    //1. Declare and register the virtual machine in direct mode
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange("direct_order_exchange", true, false);
    }

    //2. Claim queue
    @Bean
    public Queue directSmsQueue() {
        return new Queue("sms.direct.queue", true);
    }

    @Bean
    public Queue directEmailQueue() {
        return new Queue("email.direct.queue", true);
    }

    @Bean
    public Queue directDuanxinQueue() {
        return new Queue("duanxin.direct.queue", true);
    }

    //3. Complete the binding relationship
    @Bean
    public Binding directSmsBinding() {
        return BindingBuilder.bind(directSmsQueue()).to(directExchange()).with("sms");
    }

    @Bean
    public Binding directEmailBinding() {
        return BindingBuilder.bind(directEmailQueue()).to(directExchange()).with("email");
    }

    @Bean
    public Binding directDuanxinBinding() {
        return BindingBuilder.bind(directDuanxinQueue()).to(directExchange()).with("duanxin");
    }
}
Additional knowledge point 1:

1).

new DirectExchange((String name, boolean durable, boolean autoDelete);

Name: exchanger name

durable: persistent or not
Rabbitmq stores messages in memory by default. If rabbitmq goes down and rabbitmq is restarted, the messages will be lost. If you want to exist after restarting, you need to make the queue persistent (set the durable attribute to true) and save it to the Mnesia database of Erlang. When rabbitmq is restarted, the database will be read.

autoDelete: whether to delete automatically
When the autoDelete property is set to true, the message queue will be deleted when the message receiver goes down. The message sender will always send messages. When the message receiver restarts and returns to normal, it will receive the latest messages, and the messages during the downtime will be discarded.

When the autoDelete attribute is set to false, the message queue will not be deleted after the message receiver is shut down, and the message sender will always send messages. When the message receiver restarts and returns to normal, the messages and new messages during the downtime will be received.

2).

new Queue(String name, boolean durable)

Name: queue name
durable: persistent, ibid
3).

BindingBuilder.bind(directSmsQueue()).to(directExchange()).with("sms")

Connect RoutingExChange to queue "sms direct. Queue "binding, set routingKey as sms

10.4.2.Fanout mode:

FanoutRabbitMqConfiguration.java

@Configuration
public class FanoutRabbitMqConfiguration {
    //1. Declare and register the virtual machine in fanout mode
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanout_order_exchange", true, false);
    }

    //2. Claim queue
    @Bean
    public Queue smsQueue() {
        return new Queue("sms.fanout.queue", true);
    }

    @Bean
    public Queue emailQueue() {
        return new Queue("email.fanout.queue", true);
    }

    @Bean
    public Queue duanxinQueue() {
        return new Queue("duanxin.fanout.queue", true);
    }

    //3. Complete the binding relationship
    @Bean
    public Binding smsBinding() {
        return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding emailBinding() {
        return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
    }

    @Bean
    public Binding duanxinBinding() {
        return BindingBuilder.bind(duanxinQueue()).to(fanoutExchange());
    }
}
Additional knowledge point 2:
BindingBuilder.bind(duanxinQueue()).to(fanoutExchange())

Careful partners will find that the binding of the foot mode is different from that of the direct mode, and the "foot" mode is missing This is because, as we mentioned above, publish and subscribe mode is a broadcast mechanism. It is a mode without routing key. As long as the queue is bound to the switch, the messages received by the switch will be forwarded to all the queues bound to it.

10.4.3.Topic mode:

TopicRabbitMqConfiguration.java

@Configuration
public class TopicRabbitMqConfiguration {
    //1. Declare and register the virtual machine in topic mode
    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange("topic_order_exchange", true, false);
    }

    //2. Claim queue SMS topic. queue email. topic. queue duanxin. topic. queue
    @Bean
    public Queue topicSmsQueue() {
        return new Queue("sms.topic.queue", true);
    }

    @Bean
    public Queue topicEmailQueue() {
        return new Queue("email.topic.queue", true);
    }

    @Bean
    public Queue topicDuanxinQueue() {
        return new Queue("duanxin.topic.queue", true);
    }

    //3. Complete the binding relationship
    @Bean
    public Binding topicSmsBinding() {
        return BindingBuilder.bind(topicSmsQueue()).to(topicExchange()).with("sms.#");
    }

    @Bean
    public Binding topicEmailBinding() {
        return BindingBuilder.bind(topicEmailQueue()).to(topicExchange()).with("*.email.#");
    }

    @Bean
    public Binding topicDuanxinBinding() {
        return BindingBuilder.bind(topicDuanxinQueue()).to(topicExchange()).with("#.duanxin.#");
    }
Additional knowledge point 3:
BindingBuilder.bind(topicEmailQueue()).to(topicExchange()).with("*.email.#");

Careful partners will find that in topic mode, when Binding routing key s, we need to set corresponding wildcards.
×××.# : Match 0 or 1 or more levels
×××. * : There can only be 1 level matching
Take the above example to explain briefly:
If the routing Key is set to: "*. email. #"
Then, when producers send messages to the following queues, they can receive messages
test.email.it,test.email.it.computer,test.email
However, the following queues cannot receive messages normally
test1.test2.email.it,test1.test2.email.it.computer,test1.test2.email
Here is just a simple example. If you don't understand, please continue to look down at "Xi. Detailed explanation of RabbitMQ management interface"

  1. Three modes of consumer code implementation
10.5.1. Direct mode consumer code:

DirectDuanxinConsumer.java

@Service
public class DirectDuanxinConsumer {
    @RabbitListener(queues = {"duanxin.direct.queue"})
    public void reviceMessage(String message) {
        System.out.println("duanxin direct---The order information received is:->" + message);
    }
}

DirectEmailConsumer.java

@Service
public class DirectEmailConsumer {
    @RabbitListener(queues = {"email.direct.queue"})
    public void reviceMessage(String message) {
        System.out.println("email direct---The order information received is:->" + message);
    }
}

DirectSmsConsumer.java

@Service
public class DirectSmsConsumer {
    @RabbitListener(queues = {"sms.direct.queue"})
    public void reviceMessage(String message) {
        System.out.println("sms direct---The order information received is:->" + message);
    }
}
10.5.2. Fanout mode consumer code:

FanoutDuanxinConsumer.java

@Service
public class FanoutDuanxinConsumer {
    @RabbitListener(queues = {"duanxin.fanout.queue"})
    public void reviceMessage(String message) {
        System.out.println("duanxin fanout---The order information received is:->" + message);
    }
}

FanoutEmailConsumer.java

@Service
public class FanoutEmailConsumer {
    @RabbitListener(queues = {"email.fanout.queue"})
    public void reviceMessage(String message) {
        System.out.println("email fanout---The order information received is:->" + message);
    }
}

FanoutSmsConsumer.java

@Service
public class FanoutSmsConsumer {
    @RabbitListener(queues = {"sms.fanout.queue"})
    public void reviceMessage(String message) {
        System.out.println("sms fanout---The order information received is:->" + message);
    }
}
10.5.3. Topic mode consumer code:

TopicDuanxinConsumer.java

@Service
public class TopicDuanxinConsumer {
    @RabbitListener(queues = {"duanxin.topic.queue"})
    public void reviceMessage(String message) {
        System.out.println("duanxin topic---The order information received is:->" + message);
    }
}

TopicEmailConsumer.java

@Service
public class TopicEmailConsumer {
    @RabbitListener(queues = {"email.topic.queue"})
    public void reviceMessage(String message) {
        System.out.println("email topic---The order information received is:->" + message);
    }
}

TopicSmsConsumer.java

@Service
public class TopicSmsConsumer {
    @RabbitListener(queues = {"sms.topic.queue"})
    public void reviceMessage(String message) {
        System.out.println("sms topic---The order information received is:->" + message);
    }
}
  1. Operation effect of three modes
    1. Run the test codes of the three test classes in "producer" respectively (write test classes in "9.5" above)
    2. View the consumer's console output message
-Operation result of Mount mode:

producer:

consumer:

-Direct mode operation result:

producer:

consumer:

-Running results in Topic mode:

producer:

consumer:

11, Detailed explanation of RabbitMQ management interface

Thank you very much for reading here patiently. Due to the long length, it may be a little tired to read. The following content will continue to be shared with you in the next article. 🎉 Thank you for your support 🎉

11.1 enter the login interface

11.2 summary interface

11.3 connection interface

11.4 channel interface

11.5 switch page

11.6 queue interface

11.7 Admin interface

11.8 Topic mode instance practice

If you find any mistakes in the article, I hope you can give criticism and correction in the comment area 🤝 If you think the article of nickname has helped you, please follow the column of nickname [RabbitMQ] to support nickname 😄, Praise the article of nickname 👍, comment ✍, Collection 🤞 Thank you~ ♥♥♥

Keywords: MySQL CentOS RabbitMQ Spring Boot Middleware

Added by s_dhumal on Wed, 23 Feb 2022 02:51:16 +0200