Message queue MQ -- Spring Boot integration RabbitMQ

Catalogue of series articles

Message queue MQ (I) -- introduction, installation and use of management page of RabbitMQ
Message queue MQ (II) -- Spring Boot integration RabbitMQ

preface

The full name of MQ is Message Queue. Message Queue is the communication method between applications. RabbitMQ is an open source implementation of AMQP (Advanced Message Queuing Protocol) developed by Erlang.

In the project, some time-consuming operations that do not need immediate return can be extracted for asynchronous processing, which greatly saves the server's request response time and improves the system throughput.

Tip: the following is the main content of this article. The following cases can be used for reference

1, Introduction

In the spring boot project, you only need to introduce the start AMQP start dependency to integrate RabbitMQ successfully; Based on the RabbitTemplate template template object encapsulated by SpringBoot, we can easily send and receive messages (using annotations).

Official GitHub address of amqp: https://github.com/spring-projects/spring-amqp

2, Construction works

Create a SpringBoot parent project and check the initial dependency; Create two sub projects - Producer and Consumer

1. Create P system (producer)

Similarly, create the SpringBoot producer project: rabbitmq producer

pom.xml file is as follows:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.9.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
	<!--amqp Protocol start dependent coordinates-->
	<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
	</dependency>
	
	<!--rabbit Test dependent coordinates-->
	<dependency>
	<groupId>org.springframework.amqp</groupId>
	<artifactId>spring-rabbit-test</artifactId>
	<scope>test</scope>
	</dependency>
	
	<!--SpringBoot Test dependent coordinates-->
	<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
	</dependency>
</dependencies>

1.1 yml configuring RabbitMQ properties

# RabbitMQ service host address
spring.rabbitmq.host=121.138.152.111

# port
spring.rabbitmq.port=5672

# Virtual host address
spring.rabbitmq.virtual-host=/demo

# User name of the rabbit service
spring.rabbitmq.username=demo

# Password for rabbit service
spring.rabbitmq.password=demo

2. Create C system (consumer)

Similarly, create a SpringBoot consumer project: rabbitmq consumer

pom.xml file is as follows:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.9.RELEASE</version>
	<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
	<!--amqp Start dependent coordinates-->
	<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
	</dependency>
</dependencies>

2.1 yml configuring RabbitMQ properties

# RabbitMQ service host address
spring.rabbitmq.host=121.138.152.111

# port
spring.rabbitmq.port=5672

# Virtual host address
spring.rabbitmq.virtual-host=/demo

# User name of the rabbit service
spring.rabbitmq.username=demo

# Password for rabbit service
spring.rabbitmq.password=demo

3, Five operating modes of RabbitMQ

The five working modes are an iterative relationship,
① For example, the simple mode is one-to-one;
② What should I do if I have two or even more consumers? There is a work queue mode, one to many;
③ Now I think there are too many consumers and too few queues, so I introduce multiple queues corresponding to different consumers, which leads to the publish subscribe mode;
④ Now I just want to send messages to the message queue of one of the consumers. What to do if others don't send messages, so there is a Routing mode;
⑤ But the problem comes again. Now I want to send a certain message type to a queue. The one-to-one correspondence of routing modes is too strict. What should I do? There is a wildcard (topic) pattern.

3.1 HelloWorld simple mode

Introduction: in the above model, P is called the producer (the program that actively sends messages), and C is called the consumer (the receiver of the message will always wait for the arrival of the message). The relationship between the two is one attack and one receive (dog head). Queue: red part, message queue. Producers deliver messages and consumers take messages from them. This is the simple message queue pattern.

3.1.1 RabbitMQ management interface operation

Create simple_queue message queue is used to demonstrate the simple pattern of Hello World

Click simple_queue enters the message queue management page

Click Get_Message can view the messages obtained in the queue

3.1.2 coding

The test code of rabbitmq producer project is as follows:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo01TestSimpleQueue {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Test
	public void contextLoads() {
		//Send a simple message to the message queue
		/**
		* Parameter 1: message queue name
		* Parameter 2: message content
		*/
		rabbitTemplate.convertAndSend("simple_queue","hello Little rabbit!");
	}
}

Rabbitmq consumer project creates a listener to receive messages:

/**
* Consumer, receive message queue, message listener
* The current listener object must be injected into the Spring container
*/
@Component
@RabbitListener(queues = "simple_queue")
public class SimpleListener {
	@RabbitHandler
	public void simpleHandler(String msg){
		System.out.println("=====receive messages====>"+msg);
	}
}

Start the SpringbootRabbitmqConsumerApplication, and you can receive the message sent by the RabbitMQ server

3.2 Work queues mode


Introduction: compared with the simple queue mode, Work Queue has one or more consumers, and multiple consumers consume messages in the same queue together. Originally one-to-one, now one to many, so in this mode, consumers compete for messages in the message queue.

3.2.1 RabbitMQ management interface operation

Create work_queue queue is used to demonstrate the work queue mode

3.2.2 coding

Producer Code:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo02TestWorkQueue {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Test
	public void contextLoads() {
		//Send 1000 messages to the work queue
		for (int i = 0; i < 1000; i++) {
			/**
			* Parameter 1: message queue name
			* Parameter 2: message content
			*/
			rabbitTemplate.convertAndSend("work_queue","hello I'm a rabbit
			["+i+"]!");
		}
	}
}

Consumer 1 Code:

/**
* Work queue: the consumer receives listener 1 and receives messages from the message queue
*/
@Component
@RabbitListener(queues = "work_queue")
public class WorkListener1 {
	@RabbitHandler
	public void workHandler(String msg){
		System.out.println("=====Work queue receive message side 1====>"+msg);
	}
}

Consumer 2 Code:

/**
 * Work queue: the consumer receives listener 2 and receives messages from the message queue
*/
@Component
@RabbitListener(queues = "work_queue")
public class WorkListener2 {
	@RabbitHandler
	public void workHandler(String msg){
		System.out.println("=====Work queue message receiver 2====>"+msg);
	}
}

3.3 Publish/Subscribe publishing and subscription mode


Introduction: in the subscriber model, there is an exchange, that is, a switch.
1. Each consumer listens to their own queue.
2. The producer sends the message to the broker, and the switch forwards the message to each queue bound to the switch, and each queue bound to the switch will receive the message
[broadcast message: send the message to all consumers at one time, and each consumer receives the same message]

  • P: The producer, that is, the program that sends the message, but it is no longer sent to the queue, but to X (switch)
  • C: Consumers, the recipients of news, will always wait for the news to come.
  • Queue: message queue, receiving messages and caching messages.
  • Exchange: switch, X in figure. On the one hand, it receives messages sent by producers. On the other hand, you know how to process messages, such as delivering to a special queue, delivering to all queues, or discarding messages. How to operate depends on the type of exchange.

exchange type:

  • Fanout: the broadcast gives the message to all queues bound to the switch and does not process the routing key. Simply bind the queue to
    On the switch. fanout type switches are the fastest to forward messages.
  • Direct: direct the message to the queue matching the specified routing key. Process the routing key. A queue needs to be bound to the exchange
    On the machine, the message is required to exactly match a specific routing key. If a queue is bound to the switch, a routing key is required
    "Dog", only the messages marked as "dog" will be forwarded, and neither dog.puppy nor dog.guard will be forwarded,
    Only dog will be forwarded.
    Among them, the routing mode uses a direct switch.
  • Topic: the topic (wildcard) gives the message to the queue that conforms to the routing pattern. Enter the routing key and a pattern
    Row matching. At this time, the queue needs to be bound to a pattern. The symbol '#' matches one or more words, and the symbol '' matches no more than one
    Words. Therefore, "audit. #" can match "audit.irs. Corporation", but "audit." will only match "audit.irs".
    Among them, the topic mode (wildcard mode) uses topic type switches.

Exchange (switch) is only responsible for forwarding messages and does not have the ability to store messages. Therefore, if there is no queue bound to exchange or no queue that meets the routing rules, messages will be lost

3.3.1 RabbitMQ management interface operation

Create two queues fanout_queue1 and fanout_queue2

Create Exchange switch fanout_exchange

Fanout to be created_ Exchange and fanout_queue1, fanout_queue2 queue binding

3.3.2 code editing

Rabbitmq producer Code:

/**
* Target: send the message to the switch and broadcast it to the message queue through the switch. The routing key is an empty string
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo03TestPublishAndSubscribe {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Test
	public void contextLoads() {
		//Send 1000 messages to the broadcast switch
		for (int i = 0; i < 1000; i++) {
			/**
			* Parameter 1: switch name
			* Parameter 2: routing key
			* Parameter 3: message content
			*/
			rabbitTemplate.convertAndSend("fanout_exchange","","hello I'm a little girl
			Rabbit["+i+"]!");
		}
	}
}

Consumer 1 (rabbitmq consumer) code:

/**
* Publish subscribe mode: Message Listening 1
*/
@Component
@RabbitListener(queues = "fanout_queue1")
public class PubAndSubListener1 {
@RabbitHandler
public void pubAndSubHandler(String msg){
		System.out.println("=====Publish subscribe mode receiving message end [1]=====>"+msg);
	}
}

Consumer 2 (rabbitmq consumer) code:

/**
* Publish subscribe mode: Message Listening 2
*/
@Component
@RabbitListener(queues = "fanout_queue2")
public class PubAndSubListener2 {
	@RabbitHandler
	public void pubAndSubHandler(String msg){
		System.out.println("=====Publish subscribe mode receiving message end [2]=====>"+msg);
	}
}

3.4 Routing mode


Introduction: routing mode features: the binding between queue and switch cannot be arbitrary, but a routing key should be specified When sending a message to exchange, the sender of the message must also specify the routingkey of the message. Exchange will no longer hand over the message to each bound queue, but judge according to the routing key of the message. The message will be received only if the routingkey of the queue is completely consistent with the routing key of the message.

[illustration]
P: The producer sends messages to Exchange. When sending messages, a routing key will be specified.
10: Exchange (exchange) receives the producer's message, and then submits the message to the queue that exactly matches the routing key
C1: consumer, whose queue specifies the message whose routing key is error
C2: consumer, whose queue specifies the messages whose routing key needs to be info, error and warning
[selective message reception]

3.4.1 RabbitMQ management interface operation

Create two queues called routing_queue1 and routing_queue2 user presentations

Create a routing_exchange of type direct, which is used to demonstrate the routing mode

Setting binding: bind the created switches routing_exchange, routing_queue1 and routing_queue2 together. The routing keys are info and error respectively

3.4.2 code editing

The rabbitmq producer code is as follows:

/**
* Target: send the message to the switch, route it to the specified message queue through the switch, and specify it through the routing key class
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04TestRoutingModel {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Test
	public void contextLoads() {
		//Send 1000 messages to routing switch
		for (int i = 0; i < 1000; i++) {
			/**
			* Parameter 1: switch name
			* Parameter 2: routing key: error, info, specifies the message queue to be delivered
			* Parameter 3: message content
			*/
			if(i%2 == 0){
				rabbitTemplate.convertAndSend("routing_exchange","info","hello I'm a rabbit["+i+"]!");
			} else {
				rabbitTemplate.convertAndSend("routing_exchange","error","hello I'm a rabbit["+i+"]!");
			}
		}
	}
}

Consumer 1 (rabbitmq consumer) code is as follows:

/**
* Routing mode: message queue receiving listener 1 receives messages sent from the routing mode
*/
@Component
@RabbitListener(queues = "routing_queue1")
public class RoutingListener1 {
	@RabbitHandler
	public void routingHandler(String msg){
		System.out.println("=====Routing mode message receiving listener [1]=====>"+msg);
	}
}

Consumer 2 (rabbitmq consumer) code is as follows:

/**
* Routing mode: the message queue receiving listener 2 receives messages sent from the routing mode
*/
@Component
@RabbitListener(queues = "routing_queue2")
public class RoutingListener2 {
	@RabbitHandler
	public void routingHandler(String msg){
		System.out.println("=====Routing mode message receiving listener [2]=====>"+msg);
	}
}

3.5 Topics wildcard mode (topic mode)


Introduction:
Compared with Direct, Topic type can route messages to different queues according to RoutingKey. However, Topic type Exchange allows queues to use wildcards when Binding Routing key!

Routingkey: generally, it is composed of one or more words. Multiple words are separated by ".", such as item.insert

Wildcard rule:
#: matches one or more words separated by a dot
❉: no more, no less, exactly one word
give an example:
Item. #: it can match item.insert.abc.bbc or item.insert
Item. *: only item.insert can be matched

3.5.1 RabbitMQ management interface operation

Create queues topic_queue1 and topic_queue1

Create an exchange topic_exchange with type topic

Set binding:
The Routing Key bound by topic_queue1 is item*
The Routing Key bound by topic_queue2 is item#

3.5.2 code editing

The rabbitmq producer code is as follows:

/**
* Target: send the message to the switch and route it to the specified message queue through the switch. The routing key uses wildcards
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo05TestTopicModel {
	@Autowired
	private RabbitTemplate rabbitTemplate;
	@Test
	public void contextLoads() {
		//Send message to switch
		rabbitTemplate.convertAndSend("topic_exchange","item.insert","hello
		I'm bunny, routing key item.insert");
		rabbitTemplate.convertAndSend("topic_exchange","item.insert.abc","hello I
		It's a bunny, routing key: item.insert.abc");
	}
}

Consumer 1 (rabbitmq producer) code is as follows:

/**
* Wildcard mode: the message queue receiving listener 1 receives messages sent from the wildcard mode
*
*/
@Component
@RabbitListener(queues = "topic_queue1")
public class TopicListener1 {
	@RabbitHandler
	public void topicHandler(String msg){
		System.out.println("=====Wildcard mode message receiving listener [1]=====>"+msg);
	}
}

Consumer 2 (rabbitmq producer) code is as follows:

/**
* Wildcard mode: the message queue receiving listener 1 receives messages sent from the wildcard mode
*
*/
@Component
@RabbitListener(queues = "topic_queue2")
public class TopicListener2 {
	@RabbitHandler
	public void topicHandler(String msg){
		System.out.println("=====Wildcard mode message receiving listener [2]=====>"+msg);
	}
}

summary

Working mode:
1. Simple mode HelloWorld: one producer, one consumer, no need to set the switch (use the default switch)

2. Work Queue mode Work Queue: one producer and multiple consumers (competitive relationship), and there is no need to set up a switch (using default)
(approved switch)

3. Publish/subscribe mode: the switch of fanout type needs to be set, and the switch is bound to the queue,
When the message is sent to the switch, the exchange sends the message broadcast to the bound queue

4. Routing mode: you need to set the switch of type direct, bind the switch to the queue, and specify routing
Key. After sending a message to the switch, the switch will send the message to the corresponding queue according to the routing key

5. Wildcard mode topic: you need to set the switch of type topic, bind the switch to the queue, and specify the wildcard mode
After sending a message to the switch, the switch will send the message to the corresponding queue according to the routing key

Keywords: Java RabbitMQ Spring Spring Boot

Added by jjk-duffy on Tue, 28 Sep 2021 11:12:56 +0300