The original source: pure smile
RabbitMQ is a message queue, which is mainly used to implement asynchronous and decoupled applications, but also can serve as message buffering and message distribution.
Message middleware in the use of Internet companies more and more, just saw news Ali will ROCKETMQ donated to Apache, of course, today's protagonist is still talking about RABBITMQ. The most important role of message middleware is decoupling, the most standard use of middleware is the producer of the production of messages to the queue, consumers take messages from the queue and processing, producers do not care who is to consume, consumers do not care who in the production of the message, thereby achieving the purpose of decoupling. In distributed systems, Message Queuing is also used in many other ways, such as: Support for distributed transactions, RPC calls, and so on.
Used to be activemq, in the actual production use also appeared some small problems, after the network consulted a lot of information, decided to try to use RABBITMQ to replace the ACTIVEMQ,RABBITMQ high availability, high performance, flexibility and other features attracted us, Some data were consulted to sort out this article.
RABBITMQ Introduction
RABBITMQ is one of the messaging middleware implementations of the AMQP (Advanced Message Queuing Protocol) that originated in the financial system and is used to store and forward messages in distributed systems, with good performance in terms of ease of use, scalability, and high availability. RABBITMQ is mainly implemented to realize the bidirectional decoupling between the systems. When producers produce large amounts of data, consumers cannot consume quickly, and a middle tier is needed. Save this data.
AMQP, Advanced message Queuing Protocol, is an open standard for application-layer protocols designed for message-oriented middleware. Message middleware is mainly used for decoupling between components, the sender of the message does not need to know the existence of the message consumer, and vice versa. The main features of AMQP are message-oriented, queue, routing (including point-to-point and publish/subscribe), reliability, and security.
RABBITMQ is an open-source AMQP implementation that is written in Erlang and supported by a variety of clients such as Python, Ruby,. NET, Java, JMS, C, PHP, ActionScript, XMPP, stomp, etc., and support Ajax. It is used to store and forward messages in distributed system, which is very good in ease of use, extensibility, high availability and so on.
Related concepts
Usually we talk about the queue service, there are three concepts: the sender, the queue, the receiver, RabbitMQ on this basic concept, more than a layer of abstraction, between the sender and the queue, joined the switch (Exchange). In this way, the sender and the queue are not directly connected, and instead become the sender of the message to the exchanger, the switch according to the scheduling policy and then the message to the queue.
- The left P represents the producer, the program that sends messages to the RabbitMQ.
- The middle is the RabbitMQ, which includes the switches and queues.
- The right side C represents the consumer, that is, the program to get the message to RabbitMQ.
Then, there are 4 more important concepts, namely: virtual host, switch, queue, and binding.
- Virtual Host: A virtual host holds a set of switches, queues, and bindings. Why do you need multiple virtual hosts? Very simple, RABBITMQ, the user can only be in the granularity of the virtual host permissions control. Therefore, if you need to prohibit group A from accessing the switch/queue/bindings for Group B, you must create a virtual host for A and b respectively. Each of the RABBITMQ servers has a default virtual host "/".
- Switch: Exchange is used to forward messages, but it does not store, and if there is no Queue bind to Exchange, it discards the messages sent by Producer directly. Here is a more important concept: the routing key. When the message is to the switch, the interaction is forwarded to the corresponding queue, and then to which queue it is forwarded depends on the routing key.
- Bindings: That is, the switch needs to be bound to the queue, which, as shown, is a many-to-many relationship.
Switch (Exchange)
The function of the switch is to receive the message and forward it to the bound queue, the switch does not store the message, and when ACK mode is enabled, the switch cannot find the queue and returns an error. There are four types of switches: Direct, topic, Headers and Fanout
- The behavior of the Direct:direct type is "match first, then deliver". That is, when the binding is set to a routing_key, the routing_key of the message matches, the switch is delivered to the bound queue.
- Topic: Forwarding messages by rules (most flexible)
- Headers: Switch to set header attribute parameter type
- Fanout: Forwarding messages to all bound queues
Direct Exchange
Direct Exchange is the RABBITMQ default switch mode and the simplest mode to find queues based on key full-text matching.
The first x–q1 has a binding key named Orange, and X–Q2 has 2 binding keys named Black and green. When the routing key in the message corresponds to the binding key, you know which queue the message goes to.
Ps: Why X to Q2 to have black,green,2 a binding key, one not on the line? – This is mainly because there may be Q3, and Q3 only accepts Black's message, and Q2 not only accepts Black's message, but also accepts Green's message.
Topic Exchange
Topic Exchange forwarding messages are primarily based on wildcard characters. Under this switch, the queue and switch bindings define a route pattern, so the wildcard must match the routing pattern and the routing key before the switch can forward the message.
In this switch mode:
- The routing key must be a string of characters separated by a period (.), such as agreements.us, or Agreements.eu.stockholm.
- The route pattern must contain an asterisk (*), which is used primarily to match a word in the location specified by the routing key, for example, a route pattern like this: agreements. B.*, then only the routing key is matched: the first word is agreements, and the fourth Word is B. The pound sign (#) is equivalent to one or more words, such as a matching pattern is agreements.eu.berlin.#, then the routing key starting with Agreements.eu.berlin is OK.
The exact code is sent at the same time, the first parameter represents the switch, the second parameter represents routing key, and the third parameter is a message. As follows:
rabbitTemplate.convertAndSend(
"testTopicExchange"
,
"key1.a.c.key2"
,
" this is RabbitMQ!"
);
Topic is similar to direct, except that "mode" is supported on the match, and in the Routing_key form of "dot", two wildcard characters can be used:
- * Denotes a word.
- #表示零个或多个词.
Headers Exchange
Headers is also based on rule matching, and headers is a type of custom matching rule that uses routing_key in a fixed manner compared to direct and topic. When a queue is bound to a switch, a set of key-value pairs is set, and the message includes a set of key-value pairs (the headers attribute) that are delivered to the corresponding queue when the pair of key-value pairs, or all of them, match.
fanout Exchange
Fanout Exchange message Broadcast mode, regardless of the routing key or route pattern, sends the message to all queues bound to it, and if configured Routing_key is ignored.
Springboot Integrated RABBITMQ
Springboot Integrated RABBITMQ is very simple, if only a simple use configuration is very small, Springboot provides various support for the SPRING-BOOT-STARTER-AMQP project to the message.
Simple to use
1, the configuration Pom package, mainly add SPRING-BOOT-STARTER-AMQP support
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2. Configuration files
Configure the installation address, port, and account information for the RABBITMQ
spring.application.name=spirng-boot-rabbitmq
spring.rabbitmq.host=
192.168
.
0.86
spring.rabbitmq.port=
5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=
123456
3. Queue Configuration
@Configuration
public
class
RabbitConfig {
@Bean
public
Queue Queue() {
return
new
Queue(
"hello"
);
}
}
3. Sender
Rabbittemplate is the default implementation provided by Springboot
public
class
HelloSender {
@Autowired
private
AmqpTemplate rabbitTemplate;
public
void
send() {
String context =
"hello "
+
new
Date();
System.out.println(
"Sender : "
+ context);
this
.rabbitTemplate.convertAndSend(
"hello"
, context);
}
}
4. Recipient
@Component
@RabbitListener
(queues =
"hello"
)
public
class
HelloReceiver {
@RabbitHandler
public
void
process(String hello) {
System.out.println(
"Receiver : "
+ hello);
}
}
5. Testing
@RunWith
(SpringRunner.
class
)
@SpringBootTest
public
class
RabbitMqHelloTest {
@Autowired
private
HelloSender helloSender;
@Test
public
void
hello()
throws
Exception {
helloSender.send();
}
}
Note that the queue name of the sender and receiver must be the same, or it cannot receive
Many-to-many use
What happens to a sender, n receivers or N senders and n receivers?
One -to-many sends
The above code is a small modification, the receiver registered two receiver,receiver1 and Receiver2, the sender to join the parameter count, the receiver to print the received parameters, the following is the test code, send 100 messages, to observe the performance of two receiving end
@Test
public
void
oneToMany()
throws
Exception {
for
(
int
i=
0
;i<
100
;i++){
neoSender.send(i);
}
}
The results are as follows:
Receiver
1
: spirng boot neo queue ******
11
Receiver
2
: spirng boot neo queue ******
12
Receiver
2
: spirng boot neo queue ******
14
Receiver
1
: spirng boot neo queue ******
13
Receiver
2
: spirng boot neo queue ******
15
Receiver
1
: spirng boot neo queue ******
16
Receiver
1
: spirng boot neo queue ******
18
Receiver
2
: spirng boot neo queue ******
17
Receiver
2
: spirng boot neo queue ******
19
Receiver
1
: spirng boot neo queue ******
20
The following conclusions are obtained based on the results returned
A sender, n a receiver, is tested to send messages evenly to n receivers
Many-to-many sends
Copies a sender, adds tags, and alternately sends each other in 100 loops
@Test
public
void
manyToMany()
throws
Exception {
for
(
int
i=
0
;i<
100
;i++){
neoSender.send(i);
neoSender2.send(i);
}
}
The results are as follows:
Receiver
1
: spirng boot neo queue ******
20
Receiver
2
: spirng boot neo queue ******
20
Receiver
1
: spirng boot neo queue ******
21
Receiver
2
: spirng boot neo queue ******
21
Receiver
1
: spirng boot neo queue ******
22
Receiver
2
: spirng boot neo queue ******
22
Receiver
1
: spirng boot neo queue ******
23
Receiver
2
: spirng boot neo queue ******
23
Receiver
1
: spirng boot neo queue ******
24
Receiver
2
: spirng boot neo queue ******
24
Receiver
1
: spirng boot neo queue ******
25
Receiver
2
: spirng boot neo queue ******
25
Conclusion: As with a one-to-many, the receiving side will still receive the message evenly.
Advanced use
Support for objects
Springboot and perfect support objects are sent and received without the need for extra configuration.
//发送者
public
void
send(User user) {
System.out.println(
"Sender object: "
+ user.toString());
this
.rabbitTemplate.convertAndSend(
"object"
, user);
}
...
//接收者
@RabbitHandler
public
void
process(User user) {
System.out.println(
"Receiver object : "
+ user);
}
The results are as follows:
Sender object: User{name=
‘neo‘
, pass=
‘123456‘
}
Receiver object : User{name=
‘neo‘
, pass=
‘123456‘
}
Topic Exchange
Topic is the most flexible way in rabbitmq, which can bind different queues according to Routing_key Freedom.
First configure the topic rule, where two queues are used to test
@Configuration
public
class
TopicRabbitConfig {
final
static
String message =
"topic.message"
;
final
static
String messages =
"topic.messages"
;
@Bean
public
Queue queueMessage() {
return
new
Queue(TopicRabbitConfig.message);
}
@Bean
public
Queue queueMessages() {
return
new
Queue(TopicRabbitConfig.messages);
}
@Bean
TopicExchange exchange() {
return
new
TopicExchange(
"exchange"
);
}
@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.#"
);
}
}
Use Queuemessages to match two queues simultaneously, queuemessage only matches "Topic.message" queue
public
void
send1() {
String context =
"hi, i am message 1"
;
System.out.println(
"Sender : "
+ context);
this
.rabbitTemplate.convertAndSend(
"exchange"
,
"topic.message"
, context);
}
public
void
send2() {
String context =
"hi, i am messages 2"
;
System.out.println(
"Sender : "
+ context);
this
.rabbitTemplate.convertAndSend(
"exchange"
,
"topic.messages"
, context);
}
Send Send1 will match to topic. #和topic. Message two receiver can receive messages, send Send2 only topic. #可以匹配所有只有Receiver2监听到消息
fanout Exchange
Fanout is the familiar broadcast mode or subscription mode that sends messages to the fanout switch, and all queues that bind the switch receive this message.
Fanout Related Configurations
@Configuration
public
class
FanoutRabbitConfig {
@Bean
public
Queue AMessage() {
return
new
Queue(
"fanout.A"
);
}
@Bean
public
Queue BMessage() {
return
new
Queue(
"fanout.B"
);
}
@Bean
public
Queue CMessage() {
return
new
Queue(
"fanout.C"
);
}
@Bean
FanoutExchange fanoutExchange() {
return
new
FanoutExchange(
"fanoutExchange"
);
}
@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
return
BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
return
BindingBuilder.bind(BMessage).to(fanoutExchange);
}
@Bean
Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {
return
BindingBuilder.bind(CMessage).to(fanoutExchange);
}
}
Here, a, B, c three queues are used to bind to the fanout switch, and any character written by the Routing_key of the sending side is ignored:
public
void
send() {
String context =
"hi, fanout msg "
;
System.out.println(
"Sender : "
+ context);
this
.rabbitTemplate.convertAndSend(
"fanoutExchange"
,
""
, context);
}
The results are as follows:
Sender : hi, fanout msg
...
fanout Receiver B: hi, fanout msg
fanout Receiver A : hi, fanout msg
fanout Receiver C: hi, fanout msg
The results show that the queues that are bound to the fanout switch receive messages
Sample code
Reference
- RabbitMQ Use reference
- Rabbitmq:spring integrated RabbitMQ with its concept, message persistence, ACK mechanism
Springboot (eight): RabbitMQ detailed