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
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
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
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.
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
2.5.2 FanoutExchange model
1.FanoutExchange message sending model
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
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
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
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