Springboot (eight): RabbitMQ detailed

Source: Internet
Author: User
Tags ack message queue switches rabbitmq

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

publicclass RabbitConfig {

@Bean

publicQueue Queue() {

returnnew Queue("hello");

}

}

3. Sender

Rabbittemplate is the default implementation provided by Springboot

publicclass HelloSender {

@Autowired

privateAmqpTemplate rabbitTemplate;

publicvoid send() {

String context = "hello "+ new Date();

System.out.println("Sender : "+ context);

this.rabbitTemplate.convertAndSend("hello", context);

}

}

4. Recipient

@Component

@RabbitListener(queues = "hello")

publicclass HelloReceiver {

@RabbitHandler

publicvoid process(String hello) {

System.out.println("Receiver  : "+ hello);

}

}

5. Testing

@RunWith(SpringRunner.class)

@SpringBootTest

publicclass RabbitMqHelloTest {

@Autowired

privateHelloSender helloSender;

@Test

publicvoid 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

publicvoid 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

publicvoid 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.

//发送者

publicvoid send(User user) {

System.out.println("Sender object: "+ user.toString());

this.rabbitTemplate.convertAndSend("object", user);

}

...

//接收者

@RabbitHandler

publicvoid 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

publicclass TopicRabbitConfig {

finalstatic String message = "topic.message";

finalstatic String messages = "topic.messages";

@Bean

publicQueue queueMessage() {

returnnew Queue(TopicRabbitConfig.message);

}

@Bean

publicQueue queueMessages() {

returnnew Queue(TopicRabbitConfig.messages);

}

@Bean

TopicExchange exchange() {

returnnew TopicExchange("exchange");

}

@Bean

Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {

returnBindingBuilder.bind(queueMessage).to(exchange).with("topic.message");

}

@Bean

Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {

returnBindingBuilder.bind(queueMessages).to(exchange).with("topic.#");

}

}

Use Queuemessages to match two queues simultaneously, queuemessage only matches "Topic.message" queue

publicvoid send1() {

String context = "hi, i am message 1";

System.out.println("Sender : "+ context);

this.rabbitTemplate.convertAndSend("exchange", "topic.message", context);

}

publicvoid 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

publicclass FanoutRabbitConfig {

@Bean

publicQueue AMessage() {

returnnew Queue("fanout.A");

}

@Bean

publicQueue BMessage() {

returnnew Queue("fanout.B");

}

@Bean

publicQueue CMessage() {

returnnew Queue("fanout.C");

}

@Bean

FanoutExchange fanoutExchange() {

returnnew FanoutExchange("fanoutExchange");

}

@Bean

Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {

returnBindingBuilder.bind(AMessage).to(fanoutExchange);

}

@Bean

Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {

returnBindingBuilder.bind(BMessage).to(fanoutExchange);

}

@Bean

Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) {

returnBindingBuilder.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:

publicvoid 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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.