[RabbitMQ Xiaobai is easy to understand, easy to learn and easy to understand]

RabbitMQ Knowledge System

1. MQ message queue

1.1. What is MQ

Message Queuing (MQ): Producer/Consumer Model
Producer: Producers continuously produce messages to the message queue
Consumers: Consumers continuously obtain messages from the message queue

1.2. Implementation method

MQ is a communication model that implements two mainstream methods of MQ: AMQP and JMS

The difference/connection between the two:

  1. JMS defines a unified interface to unify message operations; AMQP unifies the format of data interaction by specifying protocols.
  2. JMS restricts the use of the Java language; AMQP is only a protocol and does not specify the implementation method, so it is cross-language.
  3. JMS specifies two message models; AMQP's message model is richer

1.3 Common products

  1. ActiveMQ: based on JMS
  2. RabbitMQ: based on AMQP protocol, developed in erlang language, good stability
  3. RocketMQ: Based on JMS, Alibaba products, currently handed over to the Apache Foundation
  4. Kafka: distributed message system, high throughput

2.RabbitMQ

2.1 Overview of RabbitMQ

2.1.1 What is RabbitMQ

RabbitMQ is a message queue developed by the erlang language and based on the AMQP protocol

2.1.2 Working principle of RabbitMQ

insert image description here
insert image description here

The components are described as follows

  1. Broker: message queue service process, this process includes two parts: Exchange and Queue.
  2. Exchange: The message queue switch forwards the message route to a certain queue according to certain rules, and filters the message.
  3. Queue: message queue, a queue for storing messages, messages arrive at the queue and forwarded to the specified consumer.
  4. Producer: The message producer, that is, the producer client, which sends consumption to MQ.
  5. Consumer: The message consumer, that is, the consumer client, receives the message forwarded by MQ.
2.1.3 Message flow
  1. Send message process

a. The producer establishes a TCP connection with the Broker.
b. The producer establishes a channel with the Broker.
c. The producer sends the Broker through the channel message, and the Exchange forwards the message.
d.Exchange forwards the message to the specified Queue (queue).

  1. Receive message process

a. The consumer establishes a TCP connection with the Broker.
b. The consumer establishes a channel with the Broker.
c. Consumers listen to the specified Queue (queue).
d. When a message arrives on the Queue, the Broker will push the message to the consumer by default.

2.1.4 Working modes (six types)

1. Simple mode:
a message in a queue can only be consumed by one consumer

2. Work queues:
Work queues (one producer, multiple consumers, each consumer gets a unique message)
a) Rabbit uses polling to send messages to consumers on average.
insert image description here

3. Publish/Subscribe:
Publish and subscribe mode (a message sent by a producer is acquired by multiple consumers)
a) Each consumer listens to its own queue.
b) 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
insert image description here
4. Routing:
Routing mode (the message sent by the producer is mainly Determine which queue to send to according to the defined routing rules)
a) Each consumer listens to its own queue and sets the routingkey.
b) The producer sends the message to the switch, and the switch forwards the message to the specified queue according to the routingkey.
insert image description here

5. Topics:
topics (fuzzy matching routing rules, multiple queues, multiple consumers)
a) Each consumer monitors its own queue and sets a routingkey with a wildcard.
b) The producer sends the message to the broker, and the switch forwards the message to the specified queue according to the routingkey.
insert image description here

6. RPC:
The method for the client to call the server remotely. MQ can be used to realize the asynchronous call of RPC. Based on the Direct switch,
a) the client is both the producer and the consumer, sending RPC call messages to the RPC request queue, and monitoring the RPC response at the same time queue.
b) The server listens to the message of the RPC request queue, executes the method of the server after receiving the message, and obtains the result returned by the method c) The server sends the result of the
RPC method to the RPC response queue
d) The client (RPC caller) listens to the RPC The response queue receives the RPC call result.
insert image description here

2.1.5 Switch types (four types)

1. Direct Exchange
handles routing keys. Needing to bind a queue to an exchange requires that the message exactly match a specific routing key. This is a complete match. If a queue is bound to this exchange and requires the routing key "abc", only messages marked "abc" will be forwarded, neither abc.def nor dog.ghi will be forwarded, only abc will be forwarded.
insert image description here

2. Fanout Exchange (fanout switch, broadcast mode)
does not handle routing keys. You simply bind the queue to the exchange. A message sent to an exchange is forwarded to all queues bound to that exchange. Much like subnet broadcasting, every host on the subnet gets a copy of the message. Fanout switches are the fastest for forwarding messages.
insert image description here

3. Topic Exchange
matches the routing key with a pattern. At this point the queue needs to be bound to a mode. The symbol "#" matches one or more words, and the symbol "" matches no more or less than one word. So "abc.#" will match "abc.def.ghi", but "abc." will only match "abc.def".
insert image description here

4. Header Exchange (Header Exchange)
does not handle routing keys. Instead, it matches according to the headers attribute in the sent message content. Specify a set of key-value pairs when binding Queue and Exchange; when a message is sent to RabbitMQ, the headers of the message will be retrieved to match the key-value pairs specified when binding to Exchange; if there is an exact match, the message will be routed to the queue , otherwise it will not be routed to the queue. The headers attribute is a key-value pair, which can be Hashtable, and the value of the key-value pair can be of any type. The routing keys of fanout, direct, and topic all need to be in string form.
The matching rule x-match has the following two types:

x-match = all: Indicates that all key-value pairs match to receive the message
x-match = any: Indicates that as long as there is a key-value pair matching, the message can be received

2.2 Spingboot integrates RabbitMQ

2.2.0 YML configuration RabbitMQ
  #配置 rabbitMq 服务器
  rabbitmq:
    # 虚拟主机 virtual-host 可以理解为每指定一个 virtual-host 就相当于设置了一个 RabbitMQ 服务器,不同的服务器是分离执行的,不同的 virtual-host 拥有的权限和其他配置也不同
    virtualHost: /
    #设置RabbitMQ的IP地址
    host: 192.168.1.4
    #设置rabbitmq服务器连接端口(应用访问端口号是5672,不是控制面板端口号15672)
    port: 5672
    #设置rabbitmq服务器用户名  本地搭建对应的账户密码都是 guest
    username: guest
    password: guest
    #确认消息已发送到交换机(Exchange)
    publisher-confirms-type: correlated
    #确认消息已发送到队列(Queue)
    publisher-returns: true
2.2.1 Direct connection mode

configuration class

package com.asher.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class DirectRabbitConfig {
    
    

    //队列 起名:TestDirectQueue
    @Bean
    public Queue TestDirectQueue() {
    
    
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        //   return new Queue("TestDirectQueue",true,true,false);

        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("TestDirectQueue", true);
    }

    //Direct交换机 起名:TestDirectExchange
    @Bean
    DirectExchange TestDirectExchange() {
    
    
        //  return new DirectExchange("TestDirectExchange",true,true);
        return new DirectExchange("TestDirectExchange", true, false);
    }

    //绑定  将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
    // (队列与交换机是通过路由来进行绑定的,所以在传值的时候,只需要穿交换机的名称以及绑定路由的名称,交换机会自动通过路由来将消息分配到指定队列)
    @Bean
    Binding bindingDirect() {
    
    
        // 路由键routing-key为TestDirectRouting
        return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
    }
}

producer

@Resource
private RabbitTemplate rabbitTemplate;

/**
 * direct exchange(直连型交换机)  生产者
 */
@RequestMapping("/directSend")
@ResponseBody
public void directSend() {
    
    
    String body = "消息体内容";
    rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", body);
    System.out.println("rabbitmq发送直连模式消息成功。。。");
}

consumer

package com.asher.controller.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "TestDirectQueue")
public class DirectReceiver {
    
    

    @RabbitHandler
    public void process(String message) {
    
    
        System.out.println("第一个DirectReceiver消费者收到消息  : " + message);
    }
}

2.2.2 Broadcast Mode
Configuration Class

package com.asher.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutRabbitConfig {
    
    

    @Bean
    public Queue queueA() {
    
    
        return new Queue("fanout.A");
    }

    @Bean
    public Queue queueB() {
    
    
        return new Queue("fanout.B");
    }

    @Bean
    public Queue queueC() {
    
    
        return new Queue("fanout.C");
    }

    @Bean
    FanoutExchange fanoutExchange() {
    
    
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA() {
    
    
        return BindingBuilder.bind(queueA()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeB() {
    
    
        return BindingBuilder.bind(queueB()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeC() {
    
    
        return BindingBuilder.bind(queueC()).to(fanoutExchange());
    }
}

producer

  @Resource
    private RabbitTemplate rabbitTemplate;
    
    
     /**
     * fanout exchange(扇形交换机,广播模式)  生产者
     */
    @RequestMapping("/fanoutSend")
    @ResponseBody
    public void fanoutSend() {
    
    
        String body = "消息体内容";
        // 将数据添加进队列(根据性别,使用不同的routeKey)
        rabbitTemplate.convertAndSend("fanoutExchange", null, body);
        System.out.println("rabbitmq发送广播模式消息成功。。。");
    }

consumer 1

package com.asher.controller.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "fanout.A")
public class FanoutReceiverA {
    
    

    @RabbitHandler
    public void process(String message) {
    
    
        System.out.println("FanoutReceiverA消费者收到消息  :" + message);
    }
}

consumer 2

package com.asher.controller.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "fanout.B")
public class FanoutReceiverB {
    
    

    @RabbitHandler
    public void process(String message) {
    
    
        System.out.println("FanoutReceiverB消费者收到消息  :" + message);
    }
}
2.2.3 Theme mode

configuration class

package com.asher.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicRabbitConfig {
    
    

    public final static String MAN = "topic.man";
    public final static String WOMAN = "topic.woman";

    @Bean
    public Queue firstQueue() {
    
    
        return new Queue(TopicRabbitConfig.MAN);
    }

    @Bean
    public Queue secondQueue() {
    
    
        return new Queue(TopicRabbitConfig.WOMAN);
    }

    @Bean
    TopicExchange exchange() {
    
    
        return new TopicExchange("topicExchange");
    }

    //将firstQueue和topicExchange绑定,而且绑定的键值为topic.man
    //这样只要是消息携带的路由键是topic.man,才会分发到该队列
    @Bean
    Binding bindingExchangeMessage() {
    
    
        return BindingBuilder.bind(firstQueue()).to(exchange()).with(MAN);
    }

    //将secondQueue和topicExchange绑定,而且绑定的键值为用上通配路由键规则topic.#
    // 这样只要是消息携带的路由键是以topic.开头,都会分发到该队列
    @Bean
    Binding bindingExchangeMessage2() {
    
    
        return BindingBuilder.bind(secondQueue()).to(exchange()).with("topic.#");
    }
}

producer

@Resource
private RabbitTemplate rabbitTemplate;
    
/**
 * topic exchange(主题交换机)  生产者
 */
@RequestMapping("/topicSend")
@ResponseBody
public void topicSend() {
    
    
    String body = "消息体内容";
    //随机获取true 或 false
    Random random = new Random();
    if (random.nextBoolean()) {
    
    
        rabbitTemplate.convertAndSend("topicExchange", TopicRabbitConfig.MAN, body);
    } else {
    
    
        rabbitTemplate.convertAndSend("topicExchange", TopicRabbitConfig.WOMAN, body);
    }
    System.out.println("rabbitmq发送主题模式消息成功。。。");
}

consumer 1

package com.asher.controller.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "topic.man")
public class TopicManReceiver {
    
    
    @RabbitHandler
    public void process(String message) {
    
    
        System.out.println("TopicManReceiver消费者收到消息  : " + message);
    }
}

consumer 2

package com.asher.controller.receiver;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "topic.woman")
public class TopicWoManReceiver {
    
    
    @RabbitHandler
    public void process(String message) {
    
    
        System.out.println("TopicWoManReceiver消费者收到消息  : " + message);
    }
}

Guess you like

Origin blog.csdn.net/weixin_42506139/article/details/130803482