I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

Summary

The articles about RabbitMQ core message mode I have read before are all based on JavaAPI. I recently read the official document and found that these core message modes can all be implemented through Spring AMQP. So I summarized the practical skills of RabbitMQ, including the installation of RabbitMQ under Windows and Linux, and the implementation of Spring AMQP with 5 core message modes. I believe it will be helpful to friends who want to learn and review RabbitMQ.

Introduction

RabbitMQ is one of the most popular open source messaging middleware, which is widely used worldwide. RabbitMQ is lightweight and easy to deploy, and can support multiple messaging protocols. RabbitMQ can be deployed in a distributed system to meet large-scale, high-availability requirements.

Related concepts

Let's first understand the related concepts in RabbitMQ. Here we take the routing mode in the 5 message modes as an example.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Installation and configuration

Next, we introduce the installation and configuration of RabbitMQ, and provide two installation methods, Windows and Linux.

Installation under Windows

  • Install Erlang, download address: http://erlang.org/download/ot...

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Install RabbitMQ, download link: https://dl.bintray.com/rabbit...

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • After the installation is complete, enter the sbin directory under the RabbitMQ installation directory;

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Enter cmd in the address bar and press Enter to start the command line, and then enter the following command to start the management function.
rabbitmq-plugins enable rabbitmq_management

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Installation under Linux

  • Download the Docker image of rabbitmq 3.7.15;
docker pull rabbitmq:3.7.15
  • Use the Docker command to start the service;
docker run -p 5672:5672 -p 15672:15672 --name rabbitmq \
-d rabbitmq:3.7.15
  • Enter the container and open the management function;
docker exec -it rabbitmq /bin/bash
rabbitmq-plugins enable rabbitmq_management

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Turn on the firewall to facilitate external network access.
firewall-cmd --zone=public --add-port=15672/tcp --permanent
firewall-cmd --zone=public --add-port=5672/tcp --permanent
firewall-cmd --reload

Access and configuration

  • Visit the RabbitMQ management page address to check whether the installation is successful (use the server IP to access under Linux): http://localhost:15672/

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Enter the account password and log in, here use the default account password to log in: guest guest
  • Create an account and set its role as an administrator: mall mall

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Create a new virtual host as: /mall

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Click on the mall user to enter the user configuration page;

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • Configure the permissions of the virtual host for mall users;

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

  • At this point, the configuration of RabbitMQ is complete.

5 message modes

These 5 message modes are the basis for building a message application based on RabbitMQ, and we must firmly grasp them. Friends who have studied RabbitMQ should have known the Java implementation of these message modes. Here we use Spring AMQP to implement them.

Simple mode

Simple mode is the simplest message mode, it contains a producer, a consumer and a queue. The producer sends a message to the queue, and the consumer gets the message from the queue and consumes it.

Mode diagram

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Spring AMQP implementation

  • First, you need to add Spring AMQP dependencies in pom.xml;
<!--Spring AMQP依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • Then modify application.yml and add the relevant configuration of RabbitMQ;
spring:
  rabbitmq:
    host: localhost
    port: 5672
    virtual-host: /mall
    username: mall
    password: mall
    publisher-confirms: true #消息发送到交换器确认
    publisher-returns: true #消息发送到队列确认
  • Add simple mode related Java configuration, create a queue named simple.hello, a producer and a consumer;
/**
 * Created by macro on 2020/5/19.
 */
@Configuration
public class SimpleRabbitConfig {

    @Bean
    public Queue hello() {
        return new Queue("simple.hello");
    }

    @Bean
    public SimpleSender simpleSender(){
        return new SimpleSender();
    }

    @Bean
    public SimpleReceiver simpleReceiver(){
        return new SimpleReceiver();
    }

}
  • The producer sends a message to the queue simple.hello through the send method;
/**
 * Created by macro on 2020/5/19.
 */
public class SimpleSender {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSender.class);

    @Autowired
    private RabbitTemplate template;

    private static final String queueName="simple.hello";

    public void send() {
        String message = "Hello World!";
        this.template.convertAndSend(queueName, message);
        LOGGER.info(" [x] Sent '{}'", message);
    }

}
  • Consumers get messages from the queue simple.hello;
/**
 * Created by macro on 2020/5/19.
 */
@RabbitListener(queues = "simple.hello")
public class SimpleReceiver {

    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleReceiver.class);

    @RabbitHandler
    public void receive(String in) {
        LOGGER.info(" [x] Received '{}'", in);
    }

}
  • Add a test interface to the controller and call this interface to start sending messages;
/**
 * Created by macro on 2020/5/19.
 */
@Api(tags = "RabbitController", description = "RabbitMQ功能测试")
@Controller
@RequestMapping("/rabbit")
public class RabbitController {

    @Autowired
    private SimpleSender simpleSender;

    @ApiOperation("简单模式")
    @RequestMapping(value = "/simple", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult simpleTest() {
        for(int i=0;i<10;i++){
            simpleSender.send();
            ThreadUtil.sleep(1000);
        }
        return CommonResult.success(null);
    }
}
  • The results after running are as follows, you can find that the producer sends a message to the queue, and the consumer gets the message from the queue and consumes it.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Operating mode

The working mode is a mode in which messages are sent to multiple competing consumers. It includes a producer, two consumers, and a queue. Two consumers are bound to a queue at the same time. When consumers get messages to process time-consuming tasks, the idle consumers get and consume messages from the queue.

Mode diagram

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Spring AMQP implementation

  • Add work mode related Java configuration, create a queue named work.hello, a producer and two consumers;
/**
 * Created by macro on 2020/5/19.
 */
@Configuration
public class WorkRabbitConfig {

    @Bean
    public Queue workQueue() {
        return new Queue("work.hello");
    }

    @Bean
    public WorkReceiver workReceiver1() {
        return new WorkReceiver(1);
    }

    @Bean
    public WorkReceiver workReceiver2() {
        return new WorkReceiver(2);
    }

    @Bean
    public WorkSender workSender() {
        return new WorkSender();
    }

}
  • The producer sends a message to the queue work.hello through the send method, the message contains a certain number of numbers;
/**
 * Created by macro on 2020/5/19.
 */
public class WorkSender {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkSender.class);

    @Autowired
    private RabbitTemplate template;

    private static final String queueName = "work.hello";

    public void send(int index) {
        StringBuilder builder = new StringBuilder("Hello");
        int limitIndex = index % 3+1;
        for (int i = 0; i < limitIndex; i++) {
            builder.append('.');
        }
        builder.append(index+1);
        String message = builder.toString();
        template.convertAndSend(queueName, message);
        LOGGER.info(" [x] Sent '{}'", message);
    }

}
  • Two consumers get messages from the queue work.hello, named instance 1 and instance 2, respectively. The more numbers in the message, the longer it takes;
/**
 * Created by macro on 2020/5/19.
 */
@RabbitListener(queues = "work.hello")
public class WorkReceiver {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkReceiver.class);

    private final int instance;

    public WorkReceiver(int i) {
        this.instance = i;
    }

    @RabbitHandler
    public void receive(String in) {
        StopWatch watch = new StopWatch();
        watch.start();
        LOGGER.info("instance {} [x] Received '{}'", this.instance, in);
        doWork(in);
        watch.stop();
        LOGGER.info("instance {} [x] Done in {}s", this.instance, watch.getTotalTimeSeconds());
    }

    private void doWork(String in) {
        for (char ch : in.toCharArray()) {
            if (ch == '.') {
                ThreadUtil.sleep(1000);
            }
        }
    }

}
  • Add a test interface to the controller and call this interface to start sending messages;
/**
 * Created by macro on 2020/5/19.
 */
@Api(tags = "RabbitController", description = "RabbitMQ功能测试")
@Controller
@RequestMapping("/rabbit")
public class RabbitController {
    
    @Autowired
    private WorkSender workSender;

    @ApiOperation("工作模式")
    @RequestMapping(value = "/work", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult workTest() {
        for(int i=0;i<10;i++){
            workSender.send(i);
            ThreadUtil.sleep(1000);
        }
        return CommonResult.success(null);
    }
}
  • The results after the operation are as follows. It can be found that the producer sends messages containing different numbers of numbers to the queue. The instance 1 and instance 2 consumers compete with each other and consume some of the messages respectively.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Publish/subscribe model

The publish/subscribe model refers to a model in which messages are sent to multiple consumers at the same time (similar to a broadcast form). It includes a producer, two consumers, two queues, and a switch. Two consumers are bound to different queues at the same time, and the two queues are bound to the exchange. The producer sends a message to the exchange, and all consumers receive and consume the message.

Mode diagram

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Spring AMQP implementation

  • Add Java configuration related to publish/subscribe mode, create an exchange named exchange.fanout, one producer, two consumers and two anonymous queues, and bind both anonymous queues to the exchange;
/**
 * Created by macro on 2020/5/19.
 */
@Configuration
public class FanoutRabbitConfig {

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

    @Bean
    public Queue fanoutQueue1() {
        return new AnonymousQueue();
    }

    @Bean
    public Queue fanoutQueue2() {
        return new AnonymousQueue();
    }

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

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

    @Bean
    public FanoutReceiver fanoutReceiver() {
        return new FanoutReceiver();
    }

    @Bean
    public FanoutSender fanoutSender() {
        return new FanoutSender();
    }

}
  • The producer sends a message to the exchange exchange.fanout through the send method, and the message contains a certain number of numbers;
/**
 * Created by macro on 2020/5/19.
 */
public class FanoutSender {
    private static final Logger LOGGER = LoggerFactory.getLogger(FanoutSender.class);
    @Autowired
    private RabbitTemplate template;

    private static final String exchangeName = "exchange.fanout";

    public void send(int index) {
        StringBuilder builder = new StringBuilder("Hello");
        int limitIndex = index % 3 + 1;
        for (int i = 0; i < limitIndex; i++) {
            builder.append('.');
        }
        builder.append(index + 1);
        String message = builder.toString();
        template.convertAndSend(exchangeName, "", message);
        LOGGER.info(" [x] Sent '{}'", message);
    }

}
  • Consumers get messages from the bound anonymous queue. The more numbers in the message, the longer it will take. Since the consumer can get and consume messages from two queues, they can be regarded as two consumers with different names. Are instance 1 and instance 2;
/**
 * Created by macro on 2020/5/19.
 */
public class FanoutReceiver {

    private static final Logger LOGGER = LoggerFactory.getLogger(FanoutReceiver.class);

    @RabbitListener(queues = "#{fanoutQueue1.name}")
    public void receive1(String in) {
        receive(in, 1);
    }

    @RabbitListener(queues = "#{fanoutQueue2.name}")
    public void receive2(String in) {
        receive(in, 2);
    }

    private void receive(String in, int receiver) {
        StopWatch watch = new StopWatch();
        watch.start();
        LOGGER.info("instance {} [x] Received '{}'", receiver, in);
        doWork(in);
        watch.stop();
        LOGGER.info("instance {} [x] Done in {}s", receiver, watch.getTotalTimeSeconds());
    }

    private void doWork(String in) {
        for (char ch : in.toCharArray()) {
            if (ch == '.') {
                ThreadUtil.sleep(1000);
            }
        }
    }

}
  • Add a test interface to the controller and call this interface to start sending messages;
/**
 * Created by macro on 2020/5/19.
 */
@Api(tags = "RabbitController", description = "RabbitMQ功能测试")
@Controller
@RequestMapping("/rabbit")
public class RabbitController {
    
    @Autowired
    private FanoutSender fanoutSender;

    @ApiOperation("发布/订阅模式")
    @RequestMapping(value = "/fanout", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult fanoutTest() {
        for(int i=0;i<10;i++){
            fanoutSender.send(i);
            ThreadUtil.sleep(1000);
        }
        return CommonResult.success(null);
    }
}
  • The results after running are as follows. It can be found that the producer sends messages containing different numbers of numbers to the queue, and instance 1 and instance 2 simultaneously obtain and consume the messages.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Routing mode

The routing mode is a mode that can selectively send messages to multiple consumers based on the routing key. It includes a producer, two consumers, two queues, and a switch. Two consumers are bound to different queues at the same time, the two queues are bound to the switch through the routing key, the producer sends a message to the switch, the switch forwards to different queues through the routing key, and the consumer bound to the queue receives and consumes news.

Mode diagram

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Spring AMQP implementation

  • Add routing mode related Java configuration, create a switch named exchange.direct, a producer, two consumers and two anonymous queues, the queues are bound to the switch through the routing key, and the routing keys of queue 1 are orange and black , The routing keys of queue 2 are green and black;
/**
 * Created by macro on 2020/5/19.
 */
@Configuration
public class DirectRabbitConfig {

    @Bean
    public DirectExchange direct() {
        return new DirectExchange("exchange.direct");
    }

    @Bean
    public Queue directQueue1() {
        return new AnonymousQueue();
    }

    @Bean
    public Queue directQueue2() {
        return new AnonymousQueue();
    }

    @Bean
    public Binding directBinding1a(DirectExchange direct, Queue directQueue1) {
        return BindingBuilder.bind(directQueue1).to(direct).with("orange");
    }

    @Bean
    public Binding directBinding1b(DirectExchange direct, Queue directQueue1) {
        return BindingBuilder.bind(directQueue1).to(direct).with("black");
    }

    @Bean
    public Binding directBinding2a(DirectExchange direct, Queue directQueue2) {
        return BindingBuilder.bind(directQueue2).to(direct).with("green");
    }

    @Bean
    public Binding directBinding2b(DirectExchange direct, Queue directQueue2) {
        return BindingBuilder.bind(directQueue2).to(direct).with("black");
    }

    @Bean
    public DirectReceiver receiver() {
        return new DirectReceiver();
    }


    @Bean
    public DirectSender directSender() {
        return new DirectSender();
    }

}
  • The producer sends a message to the exchange exchange.direct through the send method, using different routing keys when sending, and will be forwarded to different queues according to the routing key;
/**
 * Created by macro on 2020/5/19.
 */
public class DirectSender {

    @Autowired
    private RabbitTemplate template;

    private static final String exchangeName = "exchange.direct";

    private final String[] keys = {"orange", "black", "green"};

    private static final Logger LOGGER = LoggerFactory.getLogger(DirectSender.class);

    public void send(int index) {
        StringBuilder builder = new StringBuilder("Hello to ");
        int limitIndex = index % 3;
        String key = keys[limitIndex];
        builder.append(key).append(' ');
        builder.append(index+1);
        String message = builder.toString();
        template.convertAndSend(exchangeName, key, message);
        LOGGER.info(" [x] Sent '{}'", message);
    }

}
  • Consumers get messages from the anonymous queue bound to them. Since the consumer can get and consume messages from two queues, it can be regarded as two consumers, named instance 1 and instance 2 respectively;
/**
 * Created by macro on 2020/5/19.
 */
public class DirectReceiver {
    private static final Logger LOGGER = LoggerFactory.getLogger(DirectReceiver.class);

    @RabbitListener(queues = "#{directQueue1.name}")
    public void receive1(String in){
        receive(in, 1);
    }

    @RabbitListener(queues = "#{directQueue2.name}")
    public void receive2(String in){
        receive(in, 2);
    }

    private void receive(String in, int receiver){
        StopWatch watch = new StopWatch();
        watch.start();
        LOGGER.info("instance {} [x] Received '{}'", receiver, in);
        doWork(in);
        watch.stop();
        LOGGER.info("instance {} [x] Done in {}s", receiver, watch.getTotalTimeSeconds());
    }

    private void doWork(String in){
        for (char ch : in.toCharArray()) {
            if (ch == '.') {
                ThreadUtil.sleep(1000);
            }
        }
    }

}
  • Add a test interface to the controller and call this interface to start sending messages;
/**
 * Created by macro on 2020/5/19.
 */
@Api(tags = "RabbitController", description = "RabbitMQ功能测试")
@Controller
@RequestMapping("/rabbit")
public class RabbitController {

    @Autowired
    private DirectSender directSender;

    @ApiOperation("路由模式")
    @RequestMapping(value = "/direct", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult directTest() {
        for(int i=0;i<10;i++){
            directSender.send(i);
            ThreadUtil.sleep(1000);
        }
        return CommonResult.success(null);
    }
}
  • The results after running are as follows. It can be found that the producer sends messages containing different routing keys to the queue. Instance 1 gets orange and black messages, and instance 2 gets green and black messages.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Wildcard pattern

The wildcard pattern is a pattern that can selectively send messages to multiple consumers based on routing key matching rules. It includes one producer, two consumers, two queues, and a switch. Two consumers are bound to different queues at the same time. The two queues are bound to the switch through routing key matching rules. The producer sends messages to the switch, and the switch forwards to different queues through the routing key matching rules. The queue-bound consumption The person receives and consumes the message.

Special matching symbol

  • *: Only one word can be matched;
  • #: You can match zero or more words.

Mode diagram

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Spring AMQP implementation

  • Add wildcard pattern related Java configuration, create an exchange named exchange.topic, a producer, two consumers and two anonymous queues, match *.orange.* and *.*.rabbit to queue 1, match lazy .#Send to queue 2;
/**
 * Created by macro on 2020/5/19.
 */
@Configuration
public class TopicRabbitConfig {

    @Bean
    public TopicExchange topic() {
        return new TopicExchange("exchange.topic");
    }

    @Bean
    public Queue topicQueue1() {
        return new AnonymousQueue();
    }

    @Bean
    public Queue topicQueue2() {
        return new AnonymousQueue();
    }

    @Bean
    public Binding topicBinding1a(TopicExchange topic, Queue topicQueue1) {
        return BindingBuilder.bind(topicQueue1).to(topic).with("*.orange.*");
    }

    @Bean
    public Binding topicBinding1b(TopicExchange topic, Queue topicQueue1) {
        return BindingBuilder.bind(topicQueue1).to(topic).with("*.*.rabbit");
    }

    @Bean
    public Binding topicBinding2a(TopicExchange topic, Queue topicQueue2) {
        return BindingBuilder.bind(topicQueue2).to(topic).with("lazy.#");
    }

    @Bean
    public TopicReceiver topicReceiver() {
        return new TopicReceiver();
    }

    @Bean
    public TopicSender topicSender() {
        return new TopicSender();
    }

}
  • The producer sends a message to the exchange exchange.topic through the send method, and the message contains different routing keys;
/**
 * Created by macro on 2020/5/19.
 */
public class TopicSender {

    @Autowired
    private RabbitTemplate template;

    private static final String exchangeName = "exchange.topic";

    private static final Logger LOGGER = LoggerFactory.getLogger(TopicSender.class);


    private final String[] keys = {"quick.orange.rabbit", "lazy.orange.elephant", "quick.orange.fox",
            "lazy.brown.fox", "lazy.pink.rabbit", "quick.brown.fox"};

    public void send(int index) {
        StringBuilder builder = new StringBuilder("Hello to ");
        int limitIndex = index%keys.length;
        String key = keys[limitIndex];
        builder.append(key).append(' ');
        builder.append(index+1);
        String message = builder.toString();
        template.convertAndSend(exchangeName, key, message);
        LOGGER.info(" [x] Sent '{}'",message);
        System.out.println(" [x] Sent '" + message + "'");
    }

}
  • Consumers get messages from the anonymous queue bound to them. Since the consumer can get and consume messages from two queues, it can be regarded as two consumers, named instance 1 and instance 2 respectively;
/**
 * Created by macro on 2020/5/19.
 */
public class TopicReceiver {

    private static final Logger LOGGER = LoggerFactory.getLogger(TopicReceiver.class);

    @RabbitListener(queues = "#{topicQueue1.name}")
    public void receive1(String in){
        receive(in, 1);
    }

    @RabbitListener(queues = "#{topicQueue2.name}")
    public void receive2(String in){
        receive(in, 2);
    }

    public void receive(String in, int receiver){
        StopWatch watch = new StopWatch();
        watch.start();
        LOGGER.info("instance {} [x] Received '{}'", receiver, in);
        doWork(in);
        watch.stop();
        LOGGER.info("instance {} [x] Done in {}s", receiver, watch.getTotalTimeSeconds());
    }

    private void doWork(String in){
        for (char ch : in.toCharArray()) {
            if (ch == '.') {
                ThreadUtil.sleep(1000);
            }
        }
    }

}
  • Add a test interface to the controller and call this interface to start sending messages;
/**
 * Created by macro on 2020/5/19.
 */
@Api(tags = "RabbitController", description = "RabbitMQ功能测试")
@Controller
@RequestMapping("/rabbit")
public class RabbitController {

    @Autowired
    private TopicSender topicSender;

    @ApiOperation("通配符模式")
    @RequestMapping(value = "/topic", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult topicTest() {
        for(int i=0;i<10;i++){
            topicSender.send(i);
            ThreadUtil.sleep(1000);
        }
        return CommonResult.success(null);
    }
}
  • The results of the operation are as follows. It can be found that the producer sends messages containing different routing keys to the queue, and instance 1 and instance 2 respectively obtain matching messages.

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

I don’t even understand the 5 core message modes of RabbitMQ, and dare to say that I will use message queues.

 

Reference

RabbitMQ Tutorials:https://www.rabbitmq.com/gets...

Project source address

https://github.com/macrozheng...

Guess you like

Origin blog.csdn.net/yunduo1/article/details/109116006