Spring boot (XIII): spring boot integrates rabbitmq

Time:2020-3-14

Spring boot (XIII): spring boot integrates rabbitmq

1. Preface

Rabbitmq is a message queue. When it comes to message queues, you may have heard of it more or less. Its main function is to realize asynchronous and decoupling of application services, as well as to cut peak, fill valley and distribute messages.

One of the main functions of message queuing in comparison is to decouple application services. Messages are delivered from message producers to message queues. Consumers get messages from message queues and consume them. Producers do not need to manage who consumes messages, and consumers do not need to pay attention to who produces messages. In a distributed system, message queuing will also be used in other places, such as the support of distributed transactions, representing rocketmq, which is an open source of Alibaba.

Of course, the protagonist of this article is rabbitmq.

2. Rabbitmq introduction

Rabbitmq is a kind of message middleware to realize AMQP (Advanced message queuing protocol). It originated from financial system and used to store and forward messages in distributed system. It has good performance in ease of use, scalability, high availability, etc. Rabbitmq is mainly to realize the bidirectional decoupling between systems. When producers produce a large amount of data, consumers can not consume quickly, so a middle layer is needed. Save this data.

AMQP, advanced message queuing protocol, is an open standard of application layer protocol, which is designed for message oriented middleware. Message middleware is mainly used to decouple components. The sender of message does not need to know the existence of message consumer, and vice versa. The main characteristics of AMQP are message oriented, queue oriented, routing (including point-to-point and publish / subscribe), reliability and security.

Rabbitmq is an open-source AMQP implementation. The server side is written in Erlang language, and supports a variety of clients, such as python, ruby,. Net, Java, JMS, C, PHP, ActionScript, XMPP, stomp, and Ajax. It is used to store and forward messages in the distributed system, and it has good performance in ease of use, scalability, high availability, etc.

3. Concept introduction

In the design of ordinary message queues, there are several concepts: producers, consumers and our queues. But in rabbitmq, a layer is added in the middle, called exchange. In this way, the delivery of messages is not decided by the producer, but directly delivered to the switch. The switch decides which queue the messages need to be delivered to according to the scheduling strategy. As shown in the picture:

Spring boot (XIII): spring boot integrates rabbitmq

  • The P on the left represents the producer of the message
  • Purple x stands for switch
  • Red on the right represents the queue

4. Exchange

So why do we need exchange instead of sending messages directly to the queue?

The core idea of AMQP protocol is the decoupling between producer and consumer. Producer never sends messages to queue directly. Producers often don’t know if a message will be sent to the queue, just to a switch. It is received by exchange, and then exchange forwards to queue for storage according to specific policies.

How does exchange know which queues to send when it receives a message? Here you need to understand the concepts of binding and routingkey:

Binding indicates the relationship between exchange and queue. We can also simply think that the queue is interested in messages on the switch. The binding can be accompanied by an additional parameter routingkey. Exchange matches the routingkey with the binding of all the current exchange bindings. If the matching is met, a message will be sent to the queue bound by exchange. This solves the problem that we can send a message to rabbitmq once and distribute it to different queues. The significance of routingkey depends on the type of switch.

Let’s take a look at the three main types of exchange: fanout, direct, and topic.

4.1 Direct Exchange

Spring boot (XIII): spring boot integrates rabbitmq

Direct exchange is rabbitmq’s default exchange, which routes messages completely according to routingkey. When setting the binding of exchange and queue, you need to specify routingkey (generally queue name), and the same routingkey when sending a message, and the message will be routed to the corresponding queue.

4.2 Topic Exchange

Spring boot (XIII): spring boot integrates rabbitmq

Similar to direct exchange, topic exchange also needs to route messages through routingkey. The difference is that direct exchange exactly matches routingkey, while topic exchange supports fuzzy matching. Support respectively*and#Wildcards*To match a word,#It means no or more words are matched.

4.3 Headers Exchange

Headers exchange ignores routingkey and determines which queues to route based on the headers in the message and the arguments specified when creating the binding relationship.

The performance of headers exchange is poor, and direct exchange can completely replace it, so it is not recommended.

4.4 Default Exchange

Default exchange is a special kind of direct exchange. When you manually create a queue, the background will automatically bind the queue to a direct exchange with an empty name. The binding routingkey is the same as the queue name. With this default switch and binding, we only care about the queue layer, which is more suitable for some simple applications.

5. Spring boot integrates rabbitmq

Spring boot is very simple to integrate rabbitmq. If it’s just a simple configuration, spring boot providesspring-boot-starter-amqpThe project supports various kinds of messages.

5.1 simple use

Introducing dependency

Code listing: spring boot rabbitmq / pom.xml


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

The configuration file application.yml is as follows:

Code listing: spring boot rabbitmq / SRC / main / resources / application.yml


server:
  port: 8080
spring:
  application:
    name: spring-boot-rabbitmq
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: admin

Queue configuration

Code listing: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / config / queueconfig.java


@Configuration
public class QueueConfig {
    @Bean
    public Queue simpleQueue() {
        return new Queue("simple");
    }

    @Bean
    public Queue simpleOneToMany() {
        return new Queue("simpleOneToMany");
    }
}

Message provider

Code listing: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / simple / simplesend.java


@Component
public class SimpleSend {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
  
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void send() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String message = "Hello Spring Boot " + simpleDateFormat.format(new Date());
        amqpTemplate.convertAndSend("simple", message);
        Logger.info ("message push succeeded! "";
    }
}

Message consumer

Code list: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / simple / simplereceive.java


@Component
@RabbitListener(queues = "simple")
public class SimpleReceive {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RabbitHandler
    public void process(String message) {
        logger.info("Receive :{}", message);
    }

}

test

Code listing: spring boot rabbitmq / SRC / test / Java / COM / springboot / springbootrabbitmq / demoapplicationtests.java


@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

    @Autowired
    SimpleSend simpleSend;

    @Test
    public void simpleSend() {
        simpleSend.send();
    }

}

5.2 one to many use

What happens if there is a producer of one message and a consumer of N messages?

Make some changes to the above code to add a message consumer.

The test code is as follows:

@Test
public void simpleOneSend() {
    for (int i = 0; i < 100; i ++) {
        simpleManySend.send(i);
    }
}

The test shows that two consumers consume the producer’s message on average.

5.3 many to many use

We add a message producer, and the test code is as follows:

@Test
public void simpleManySend() {
    for (int i = 0; i < 100; i ++) {
        simpleManySend.send(i);
        simpleManySend1.send(i);
    }
}

The test results show that two consumers consume the messages produced by two producers on average.

5.4 Topic Exchange

First, configure the topic. The configuration code is as follows:

Code listing: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / config / topicconfig.java


@Configuration
public class TopicConfig {

    private final String message = "topic.message";
    private final String messages = "topic.messages";

    @Bean
    public Queue queueMessage() {
        return new Queue(this.message);
    }

    @Bean
    public Queue queueMessages() {
        return new Queue(this.messages);
    }

    @Bean
    TopicExchange exchange() {
        return new TopicExchange("topicExchange");
    }

    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
    }

    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {
        return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

Here, queuemessages can match two route_keys at the same time, while queuemessages can only match topic.message.

The producer code of the message is as follows:

Code list: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / topic / topicsend.java


@Component
public class TopicSend {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send1() {
        String message = "message 1";
        logger.info("send:{}", message);
        rabbitTemplate.convertAndSend("topicExchange", "topic.message", message);
    }

    public void send2() {
        String message = "message 2";
        logger.info("send:{}", message);
        rabbitTemplate.convertAndSend("topicExchange", "topic.messages", message);
    }
}

The call to send1() is forwarded to both queues by exchange, while the call to send2() is only forwarded to receive2.

5.5 Fanout Exchange

Fanout is a familiar broadcast mode or subscription mode. It sends messages to fanout switch, and all queues bound to the switch receive the messages.

Fanout is configured as follows:

Code listing: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / config / fanoutconfig.java


@Configuration
public class FanoutConfig {
    @Bean
    public Queue MessageA() {
        return new Queue("fanout.A");
    }

    @Bean
    public Queue MessageB() {
        return new Queue("fanout.B");
    }

    @Bean
    public Queue MessageC() {
        return new Queue("fanout.C");
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA(Queue MessageA, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(MessageA).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeB(Queue MessageB, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(MessageB).to(fanoutExchange);
    }

    @Bean
    Binding bindingExchangeC(Queue MessageC, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(MessageC).to(fanoutExchange);
    }
}

The message producer code is as follows:

Code listing: spring boot rabbitmq / SRC / main / Java / COM / springboot / springbootrabbitmq / fanout / fanoutsend.java


@Component
public class FanoutSend {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String message = "Hello FanoutSend.";
        logger.info("send:{}", message);
        this.rabbitTemplate.convertAndSend("fanoutExchange","", message);
    }
}

The test code is as follows:

Code listing: spring boot rabbitmq / SRC / test / Java / COM / springboot / springbootrabbitmq / demoapplicationtests.java


@Test
public void fanoutSend() {
    fanoutSend.send();
}

The test result is that the queues bound to the fanout switch have received messages.

6. Example code

Sample code GitHub

Sample code – gitee

7. reference

http://www.ityouknow.com/spri…

https://blog.csdn.net/y4x5M0n…

Spring boot (XIII): spring boot integrates rabbitmq

If my article is helpful, please scan the code to pay attention to the official account of the author: get the latest dry cargo push:

Recommended Today

Choose react or angular 2

Original addressChoosing between React vs. Angular 2The following is the translation of this article, which can be used at your choiceReactperhapsAngular2We need to help when we need to. React has become a cool representative in 2015, but angular.js has changed from a front-end framework that people love to a terrible devil (and not so terrible…) […]