Life will be a single journey, lonely before is confused, lonely after growth.
wedge
This is the third shell of the message queue RabbitMQ.
The introduction to RabbitMQ and integration of RabbitMQ+SpringBoot can be reviewed here. Today’s lecture is on RabbitMQ switches.
It is important to understand RabbitMQ. The switch is the first stop for messages. Only by understanding the distribution pattern of the switch can we know which rules the different switches use to distribute messages and which switch should be used for different business needs.
I wish you a good harvest, praise first look, happiness is infinite.
This article code: GitHub address
1. 🔍 Exchange
I’ll start with the RabbitMQ architecture diagram I’ve been drawing for a long time, which comes up in almost every article.
In the last two articles, we haven’t used Exchange explicitly. We have used the default Exchange, but Exchange is a key component that has led to various message distribution patterns.
Let me start with a brief description of the types of Exchange:
-
Fanout: Fanout-Exchange sends messages it receives to all queues bound to it.
-
Direct: Direct-exchange sends messages it receives to a Queue to which it is bound and whose Routingkey matches exactly (the default).
-
Topic: topic-exchange is similar to direct-exchange, except that topic-exchange does not need a full match, but a partial match. It specifies: A Routingkey is a string separated by a period (.) (we call each separate string separated by a period (.) a word).
-
Header: Header-Exchange does not rely on a RoutingKey or binding to distribute messages, but matches them based on the HEADERS attribute in the content of the sent message. This pattern is no longer used and will not be covered in this article, just so you know.
In this article, we mainly talk about the first three Exchange methods, I believe that with my concise words and soul painting skills to give you a good talk, for the crone can solve.
Tip: The code in this article demonstrates the direct use of SpringBoot+RabbitMQ mode.
2. 📕 Fanout Exchange
Let’s start with a Fanout-exchange, also known as a fan Exchange, which is probably the easiest to understand.
Exchange will bind to a Queue, and Exchange will distribute messages to all queues that are bound to it.
This binding relationship will definitely maintain a table for efficiency, which is generally O(1) in terms of algorithmic efficiency, so FANout-Exchange is the fastest switch to find the queue to be distributed.
Here is a code demo:
@Bean
public Queue fanout1(a) {
return new Queue("fanout1");
}
@Bean
public Queue fanout2(a) {
return new Queue("fanout2");
}
@Bean
public FanoutExchange fanoutExchange(a) {
// Three construction parameters: Name durable autoDelete
return new FanoutExchange("fanoutExchange".false.false);
}
@Bean
public Binding binding1(a) {
return BindingBuilder.bind(fanout1()).to(fanoutExchange());
}
@Bean
public Binding binding2(a) {
return BindingBuilder.bind(fanout2()).to(fanoutExchange());
}
Copy the code
For clarity, I created two new demo queues, then a FanoutExchange, and then bound them to each other so that the set of queues and the switch were set up.
Next, write producers and consumers:
public void sendFanout(a) {
Client client = new Client();
// At the request of readers, the code will be printed in log mode in the future. This is a good programming habit, using system.out.println is generally not recommended.
log.info("Message content : " + client);
rabbitTemplate.convertAndSend("fanoutExchange".null,client);
System.out.println("Message sent.");
}
@Test
public void sendFanoutMessage(a) {
rabbitProduce.sendFanout();
}
Copy the code
@Slf4j
@Component("rabbitFanoutConsumer")
public class RabbitFanoutConsumer {
@RabbitListener(queues = "fanout1")
public void onMessage1(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed.");
}
@RabbitListener(queues = "fanout2")
public void onMessage2(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed."); }}Copy the code
Both of these pieces of code are easy to understand and will not be repeated, but you can forget the first bullet of RabbitMQ.
The code that sends the message takes three parameters. The first parameter is the name of the Exchange and the second parameter is the name of the routingKey, which is not used in the sector switch but is used in the other two switch types.
This is the end of the code preparation, we can run after the send method ~
The rabbitmqctl list_Bindings command is used on the RabbitMQ console to see if the queue/switch bindings are in effect.
The key part is highlighted in red, which means that the switch named fanoutExchange is bound to two queues, one called Fanout1 and the other fanout2.
Next, let’s look at the console print:
As you can see, once a message is sent, both queues receive the message, which is then consumed by our two consumers.
Tip: If your demo app starts with no consumption messages, try re-running the producer method to send messages.
3. 📗 Direct – Exchange
Direct-exchange is a precisely matched switch. We have been using the default switch, which is of Direct type.
If a Direct switch is the manager of an apartment, the queue is the occupants. (Binding relationship)
Administrators will receive a variety of letters (messages) every day. The address of these letters should not only indicate the address (ExchangeKey) but also indicate the routingKey to be sent to, otherwise the message cannot be delivered.
In the example above, prepare a message to send to a direct switch named SendService. The switch is mainly used for sending services, so it is bound to two queues, SMS queue and MAIL queue, for sending SMS and MAIL.
In addition to specifying an ExchangeKey, our message also needs to specify a routingKey, which corresponds to which queue is ultimately sent. In our example, the routingKey is SMS, where the message is delivered to the SMS queue.
If you’re not familiar with routingKey, let’s try it outin the last code.
Preparations:
@Bean
public Queue directQueue1(a) {
return new Queue("directQueue1");
}
@Bean
public Queue directQueue2(a) {
return new Queue("directQueue2");
}
@Bean
public DirectExchange directExchange(a) {
// Three construction parameters: Name durable autoDelete
return new DirectExchange("directExchange".false.false);
}
@Bean
public Binding directBinding1(a) {
return BindingBuilder.bind(directQueue1()).to(directExchange()).with("sms");
}
@Bean
public Binding directBinding2(a) {
return BindingBuilder.bind(directQueue2()).to(directExchange()).with("mail");
}
Copy the code
Two queues were created, a direct switch was created, and the binding relationship was set up.
The sample code here is very similar to the code for the fan switch above, except that the binding calls an extra with to set the routingKey.
So it’s the routingKey set up when the switch binds to the queue. When a message arrives on the switch, the switch finds the routingKey set up when it binds to the queue and sends the message to the queue.
Producers:
public void sendDirect(a) {
Client client = new Client();
log.info("Message content : " + client);
rabbitTemplate.convertAndSend("directExchange"."sms",client);
System.out.println("Message sent.");
}
Copy the code
Consumer:
@Slf4j
@Component("rabbitDirectConsumer")
public class RabbitDirectConsumer {
@RabbitListener(queues = "directQueue1")
public void onMessage1(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed.");
}
@RabbitListener(queues = "directQueue2")
public void onMessage2(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed."); }}Copy the code
The renderings are as follows:
Only one consumer carried out the message, in line with our expectations.
4. 📙 Topic – Exchange
A topic-exchange is a fuzzy matching version of a direct switch, a topic-type Exchange that supports fuzzy bindingkeys defined with “*” and “#” wildcards and then distributed to a fuzzy matching queue based on a routingKey.
-
* : Can fuzzy match a word.
-
# : Fuzzy match zero or more words.
The routingKey of the Topic switch has also changed somewhat due to the addition of two wildcard definitions, and routingKey can be used. Separate words.
Let’s use an example to make it clearer:
Preparations:
// Topic switch example
@Bean
public Queue topicQueue1(a) {
return new Queue("topicQueue1");
}
@Bean
public Queue topicQueue2(a) {
return new Queue("topicQueue2");
}
@Bean
public TopicExchange topicExchange(a) {
// Three construction parameters: Name durable autoDelete
return new TopicExchange("topicExchange".false.false);
}
@Bean
public Binding topicBinding1(a) {
return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with("sms.*");
}
@Bean
public Binding topicBinding2(a) {
return BindingBuilder.bind(topicQueue2()).to(topicExchange()).with("mail.#");
}
Copy the code
Two queues were created, a Topic switch was created, and bindings were set up.
The sample code here focuses on setting up a routingKey, which uses wildcards and is used in the middle. This means topicQueue1 consumes SMS messages and topicQueue2 consumes mail messages. See below.
Producers:
public void sendTopic(a) {
Client client = new Client();
log.info("Message content : " + client);
rabbitTemplate.convertAndSend("topicExchange"."sms.liantong",client);
System.out.println("Message sent.");
}
Copy the code
Consumer:
@Slf4j
@Component("rabbitTopicConsumer")
public class RabbitTopicConsumer {
@RabbitListener(queues = "topicQueue1")
public void onMessage1(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed.");
}
@RabbitListener(queues = "topicQueue2")
public void onMessage2(Message message, Channel channel) throws Exception {
log.info("Message content : " + message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
log.info("Confirmed."); }}Copy the code
The routingKey of the message sent by our producer is sms.liantong, and it will be sent to the topicQueue1 queue, where the routingKey of the message is also needed. Isolated, cannot be correctly identified with other symbols.
If our routingKey was sms.123.liantong, it would not find the corresponding queue because topicQueue1’s fuzzy match uses the wildcard * instead of #, and only # can match multiple words.
Topic-Exchange is very similar to Direct-Exchange. I won’t go over the difference between wildcard * and #.
Afterword.
Monday did not have more text true ashamed, went to the hospital to draw blood, draw three tubes ~, eat how much to fill back ~
RabbitMQ has been updated three times, these three are a bit basic, the next one will be updated with more advanced content, including preventing message loss, preventing message consumption and so on.
I’ve been under a lot of pressure lately. YouTube has asked me to upgrade to level 3 by the end of August, so your thumbs up are very important to me. I hope you can help me
Well, that’s all for this issue. Thank you for reading it here. Welcome to like, collect and comment on this article, 👍 every like from you is the biggest motivation for my creation.
I’m Ear, a pseudo-literary programmer who’s always wanted to export knowledge, and I’ll see you next time.
This article code: GitHub address