SpringCloud source code analysis (6) - Message queue RabbitMQ

1 Overview

RabbitMQ is an open source message broker and queue server developed based on the Erlang language and based on the AMQP protocol. Since the Erlang language originally used the switch domain architecture, RabbitMQ has good performance in data interaction between Brokers. AMQP (Advanced Message Queuing Protocol, Advanced Message Queuing Protocol) is a message queue application layer protocol specifically designed for message middleware. It is similar to JAVA's JMS protocol. Based on this specification, various message middleware can be developed. pieces. RabbitMQ can be perfectly integrated with SpringAMQP, has strong scalability and rich APIs, and has the advantages of high reliability and low latency, and is widely used in the industry. This article will introduce the use of SpringAMQP and Rabbit to help readers better understand message queues.

2. Use of message queue RabbitMQ

2.1 MQ comparison

Insert image description here
As can be seen from the above figure, RabbitMQ is outstanding from the perspective of reliability and message delay, but may be average from the perspective of throughput. Therefore, when selecting message queue middleware, you should choose a more appropriate one based on the usage scenario.

2.2 AMQP core concepts

name concept
Server/Broker Can be understood as a message queue entity
VHost Virtual host, there can be multiple vhosts in a broker, used to separate permissions of different users
Exchange Message switch, which specifies that messages are routed to the corresponding queue according to certain rules.
Queue Message queue carrier, each message may be put into one or more queues
Producer message producer, message delivery party
Consumer Message consumer, a program that receives messages
Binding Binder, which binds exchange and queue according to routing rules
channel Message channel, in each connection of the client, multiple channels can be established, each channel represents a session task
Routing Key Routing keyword, exchange delivers the message to the specified queue based on the keyword

2.3 RabbitMQ architecture diagram

Insert image description here

As can be seen from the above figure, the producer connects to the Broker through the channel and delivers the message to Exchange. Exchange then delivers the message to the corresponding queue according to the specified rules. The consumer obtains the message by listening to the specified queue. The producer does not need to care about which queue the message is delivered to, and the consumer does not care about which Exchange the message is sent from. The relationship between the two is loosely coupled. The types of Exchange include: Fanout switch, Direct switch, and Topic switch. Fanout switch is a broadcast mode. When a message comes in, it will be delivered to all queues bound to it. Direct switches match queues entirely based on keys, and will deliver only when the keys are consistent. Topic switches can match keys according to certain rules, and deliver the key if the match is successful.

2.4 Using RabbitMQ in SpringBoot

2.4.1 Introduce pom file

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2.4.2 Add configuration

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin

2.4.3 Writing producers

@RunWith(SpringRunner.class)
@SpringBootTest(classes = RabbitApplication.class)
public class SpringAmqpTest {
    
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSimpleQueue() {
    
    
        // 队列名称
        String queueName = "simple.queue";
        // 消息
        String message = "hello, world!";
        // 发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }

}

2.4.3 Writing consumers

@Component
public class RabbitMQListener {
    
    

    @RabbitListener(queues = "simple.queue")
    public void receiveMessage(String message) {
    
    
        System.out.println("接收到消息:" + message);
    }
}

2.4.4 Test results

Insert image description here
After running the test code, the consumer receives the message. The above code shows the most basic sending and receiving model of RabbitMQ. The generator sends the message to the specified queue, and the consumer subscribes to the specified queue to obtain the message.

2.5 RabbitMQ core message sending model

2.5.1 WorkQueue model

One queue of this model can correspond to multiple consumers. It is suitable for senders to send a large number of messages. It is easy to send backlogs, so multiple consumers are needed to consume.
Insert image description here
2.workQueue test code
Test class:

    @Test
    public void testWorkQueue() throws InterruptedException {
    
    
        // 队列名称
        String queueName = "work.queue";
        // 消息
        String message = "hello, world";

        for (int i = 1; i <= 50; i++) {
    
    
            // 发送消息
            String messageInfo = message + "..." + i;
            rabbitTemplate.convertAndSend(queueName, messageInfo);
            log.info("消息发送成功:{}", messageInfo);
            Thread.sleep(50);
        }
    }

Consumption code:

    @RabbitListener(queues = "work.queue")
    public void receiveWorkMessage1(String message) throws InterruptedException {
    
    
        System.out.println("消息队列1...接收到消息:" + message);
        Thread.sleep(10);
    }

    @RabbitListener(queues = "work.queue")
    public void receiveWorkMessage2(String message) throws InterruptedException {
    
    
        System.out.println("消息队列2...接收到消息:" + message);
        Thread.sleep(15);
    }

3.workQueue operation results
Insert image description here
Insert image description here

2.5.2 FanoutExchange model

1.FanoutExchange message sending model
Insert image description here
The FanoutExchanger model has one more switch (Exchange) than the simple model and the WorkQueue model. The message is first sent to Exchange, and then Exchange routes the message to each A queue to which it is bound.
2. Code configuration

@Configuration
public class FanoutConfig {
    
    

    @Bean
    public FanoutExchange fanoutExchange() {
    
    
        return new FanoutExchange("fanout.exchange");
    }

    @Bean
    public Queue fanoutQueue1() {
    
    
        return new Queue("fanout.queue1");
    }

    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {
    
    
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    @Bean
    public Queue fanoutQueue2() {
    
    
        return new Queue("fanout.queue2");
    }

    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange) {
    
    
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }

}

Send some test code:

  @Test
    public void testFanout() {
    
    
        // 队列名称
        String exchangeName = "fanout.exchange";
        // 消息
        String message = "hello, world!";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName,"", message);
    }

3. Running results
Insert image description here

2.5.3 DirectExchange model

The message sending mode of DirectExchange is basically the same as the FanoutExchange model. The difference is that it will route the received message to the specified Queue according to the rules. That is to say, there is an extra layer in the middle to filter the sending queue according to the rules. Each of its Each Queue has a BindingKey set with Exchange. When the publisher sends a message, it specifies the RoutingKey of the message, and Exchange routes the message to the queue whose BindingKey is consistent with the message RoutingKey.
1. The code is as follows
The listener part of the code is as follows:

 @RabbitListener(bindings = @QueueBinding(value = @Queue("direct.queue1"),exchange = @Exchange(value = "direct.exchange",type = ExchangeTypes.DIRECT),key = {
    
    "red","blue"}))
    public void receiveDirectQueue1(String message) throws InterruptedException {
    
    
        System.out.println("消息队列1...接收到消息:" + message);
    }


    @RabbitListener(bindings = @QueueBinding(value = @Queue("direct.queue2"),exchange = @Exchange(value = "direct.exchange",type = ExchangeTypes.DIRECT),key = {
    
    "red","yellow"}))
    public void receiveDirectQueue2(String message) throws InterruptedException {
    
    
        System.out.println("消息队列2...接收到消息:" + message);
    }

The test code is as follows:

 @Test
    public void testDirect() {
    
    
        // 队列名称
        String exchangeName = "direct.exchange";
        // 消息
        String message = "hello, world!";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName,"red", message);
    }

    @Test
    public void testDirectYellow() {
    
    
        // 队列名称
        String exchangeName = "direct.exchange";
        // 消息
        String message = "hello, world!";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName,"yellow", message);
    }

2. Test results
Insert image description here
Insert image description here
It can be seen from the above results that when a queue subscribes to the same Exchange and carries the RoutingKey to the specified Exchange, only the queue containing the corresponding RoutingKey can receive the message.

2.5.4 TopicExchange model

TopicExchange is similar to DirectExchange, the difference is that RoutingKey must be a list of multiple words, and separated by ., when Queue and Exchange specify BindingKey Wildcards can be used:

#: refers to 0 or more words
*: refers to one word.

1. Test code

 @RabbitListener(bindings = @QueueBinding(value = @Queue("topic.queue2"),exchange = @Exchange(value = "topic.exchange",type = ExchangeTypes.TOPIC),key = {
    
    "#.news"}))
    public void receiveTopicQueue2(String message) throws InterruptedException {
    
    
        System.out.println("消息队列2...接收到消息:" + message);
    }

Code for sending message:

@Test
    public void testTopicQueue() {
    
    
        // 队列名称
        String exchangeName = "topic.exchange";
        // 消息
        String message = "湖人总冠军";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName,"sports.news", message);
    }

2.Test results
Insert image description here

3. Summary

1.RabbitMQ is a message middleware that follows the AMQP protocol. Messages are sent from producers to consumers. It can specify the message sending object according to the rules, cache or persist it;
2. Spring AMQP is an open interface based on the AMQP protocol, which can seamlessly connect various AMQP-based protocols and quickly use Spring for development;
3. RabbitMQ has low latency and high reliability , suitable for scenarios with large throughput and high requirements for real-time information.

4. References

1.https://www.bilibili.com/video/BV1LQ4y127n4
2.https://juejin.cn/post/6844903903637536775
3.https://www.cnblogs.com/tinmh/p/6026726.html

5. Appendix

https://gitee.com/Marinc/nacos.git

Guess you like

Origin blog.csdn.net/qq_33479841/article/details/130369429