RabbitMQ 简单使用

RabbitMQ

文章目录

  • RabbitMQ
  • RabbitMQ 消息发送模式
    • 直接模式 direct
    • 发布订阅模式 fanout
    • 普通队列模式
    • 工作队列模式
    • 主题模式 topic
  • 交换机
    • 直接交换机 Direct
    • 扇形交换机
    • 主题交换机
  • springboot 整合RabbitMQ
    • 常用API
    • RabbitTemplate 常用api
    • 简单案列‼️
      • 依赖
      • 配置文件
      • 发送消息
      • 监听消息
    • 延迟队列
      • 配置类
      • 发送消息
  • 底部

RabbitMQ 消息发送模式

消息在RabbitMQ队列传输过程中,根据不同的传输方式,以及所使用的队列种类不同,一共划分了5个消息传输模式。

RabbitMQ所实现的消息投递方式来来划分,可以将消息发送模式分为两大类,点对点模式发布订阅模式;根据队列匹配规则不同发送模式分为五大类普通队列模式、工作队列模式、发布订阅模式、直接模式、主体模式

直接模式 direct

将消息直接发送给消费者

允许多个队列绑定到一个交换机上,在生产者发送消息给交换机时,需要携带一个 Key ,而这个 key 一般称为 routing key 或 binding key ,直接模式也被称为路由模式

RabbitMQ 简单使用_第1张图片

//生产者
//Routing Key 路由key名称
channel.basicPublish(EXCHANGE_NAME, "Routing Key",..)
  
//消费者
//使用channel方式绑定名为 Routin Key 的直接交换机  
channel.queueBind(QUEUE_NAME, EXCHANGE_NAME ,"Routing Key")  

发布订阅模式 fanout

生产者发布消息,消费者通过订阅的方式来消费消息(群发)

消息会发送到每一个绑定的队列上

RabbitMQ 简单使用_第2张图片

//生产者
//交换机类型指定为 fanout ,
channel.exchangeDeclare(EXCHANGE_NAME,"fanout")//fanout 交换机类型
  
//消费者
//为交换机绑定一个队列,如果没绑定队列到交换机上,则消息会丢失
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"")
//接收消息队列发送到消息并消费
channel.basicConsume(QUEUE_NAME,false,consumer)
  

普通队列模式

不使用任何交换机,由生产者,队列,消费者组合完成的发送接收

RabbitMQ 简单使用_第3张图片

//生产者
//绑定消息队列,指定消息队列的名称
channel.queueDeclare(QUEUE_NAME,false,false,false,null)
  
//消费者
//basicConsume 来接收从队列中的消息
channel.basicConsume(QUEUE_NAME,true,consumer)

工作队列模式

不使用任何交换机,由生产者、队列、消费者组合完成消息的发送和接
收,工作队列支持存在多个消费者(普通队列模式之支持一个消费者)

RabbitMQ 简单使用_第4张图片

//生产者
channel.basicPublish(QUEUE_NAME,null,message.getBytes());
Thread.sleep(1000);

//消费者
//获取队列中的消息
Delivery deliver = consumer.nextDelivery();
Thread.sleep(1000);
  • 生产者1秒发送一次消息,消费者1秒消费一次消息

主题模式 topic

交换机与消息队列所绑定的key值可以像匹配通配符的方式,来匹配消息队列。

RabbitMQ 简单使用_第5张图片

  1. .orange.: orange 两侧都可以匹配一个 key 值
    1. 123.orange.123、abd.orange.123
  2. …rabbit: 可以匹配2个key
  3. lazy.#:lazy 右侧可以匹配多个key
    1. lazy.aaa.12.323…
//生产者
//设置交换机 模式
channel.exchangeDeclare(EXCHANGE_NAME,"topic");
//消息绑定到交换机
channel.basicPublish(EXCHANGE_NAME,"key.123",..);

//消费者
//将队列绑定到交换机上,设置key 的匹配策略
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,"key.*");

交换机

主要作用: 将生产者生产出来的消息,传送到对应频道中,交换机是一个消息传递媒介,英文 exchange 。交换机在RabbitMQ中起着承上启下的作用。

常用的的三种

名称 类型
直接交换机 Direct
扇形交换机 Fanout
主题交换机 Topic

直接交换机 Direct

将消息根据特定的匹配规则发送到对应的消息队列的交换机,如果匹配规则相同,则一条消息可以被发送到多个对应的队列上,匹配规则时通过routing——key 来进行匹配

String queueName = "test_direct_x";
channel.exchangeDeclare("direct_exchange","direct");
channel.queueDeclare(queueName,true,fasle,fasle,null);

第1行,声明一个名为 test_direct_x 队列名称,对于直通交换机而言,这个名称就是 routing_key

第2行,exchangeDeclare声明一个交换机,交换机名: direct_exchange,交换机类型direct

第3行,使用queueDeclare来声明一个队列, queueName是我们声明的test_direct_x队列

RabbitMQ 简单使用_第6张图片

消息在经过 direct_exchange 交换机之后,会根据名为 test_direct_x的routing_key与相应的消息队列进行匹配,如果消息队列1,队列2,队列3都与该routing_key相匹配那么我们的消息都会全部流转到这三个消息队列中

扇形交换机

通过广播的形式,将消息传递到消息队列中,扇形交换机不需要绑定routing_key,会将消息传递到所有与该交换机绑定的消息队列中去

String queueName = "test_fanout_x";
channel.exchangeDeclare("fanout_exchange","fanout");
channel.queueBind(queueName,"fanout_exchange","");

第1行,声明了一个名为 test_fanout_x 队列。

第2行, exchangeDeclare 声明一个交换机,

第3行, queueBind 将交换机与消息队列进行绑定,

RabbitMQ 简单使用_第7张图片

消息进入 fanout_exchange 交换机之后,会首先检查有没已经与该交换机进行绑定的消息队列,没有绑定队列,消息自动失效,且抛出异常。
上图中,消息会被广播的。队列1-3中

主题交换机

routing_key 模糊匹配

String queueName = "test.topic.x";
channel.exchangeDeclare("topic_exchange","topic");
channel.queueBind(queueName,"fanout_exchange","test.#");

RabbitMQ 简单使用_第8张图片

消息静如 topic_exchange 中按照 rrouting_key 的规则去匹配队列,会去匹配每一个队列,符号规则就发送消息。

springboot 整合RabbitMQ

常用API

常用APi 作用
declareExchange() 声明交换机
declareQueue() 声明队列
declareBinding() 交换机与队列进行绑定
purgeQueue() 清空指定的队列中所有消息的方法
//交换机名 ,是否持久化,是否自动删除
new DirectExchange("test,name",false,false);
//队列名, 是否持久化
new Queue("test.name.queue",false);
@Autowired
private RabbitAdmin rabbitAdmin;
rabbitAdmin.declareExchange(new DirectExchange("test.direct", false, false));
rabbitAdmin.declareQueue(new Queue("test.direct.queue", false));
//test.name.queue 声明队列
//Binding.DestinationType.QUEUE 绑定类型
//test.name 声明交换机
// direct  交换机类型
// map 是 arguments属性 
rabbitAdmin.declareBinding(new Binding("test.name.queue", Binding.DestinationType.QUEUE,
                "test.name", "direct", new HashMap<>()));

RabbitTemplate 常用api

api 说明
MessageProperties 对消息properties参数描述
Message 对消息体进行描述
send() 将原始消息发送到RabbitMQ server中
convertAndSend() 用于原始消息进行转换,并且将转换后的消息发送到,RabbitMQ servier中
addListener() 当前消息模版设置消息监听类型
@Autowired
private RabbitTemplate rabbitTemplate;
MessageProperties messageProperties = new MessageProperties();
//获取 headers 参数
messageProperties.getHeaders().put("test1", "test1");
messageProperties.getHeaders().put("test2", "test2");
//初始化一个message  设置了 消息, 参数
Message message = new Message("Hello RabbitTemplate".getBytes(), messageProperties);

//消息转换
//test_direct_001  交换机名
//test.123   路由 routingKey
//message   发送消息
// 发送消息成功后到监听器
rabbitTemplate.convertAndSend("test_direct_001", "test.123", message, new MessagePostProcessor() {
  @Override
  public Message postProcessMessage(Message message) throws AmqpException {
  message.getMessageProperties().getHeaders().put("test1", "test111");
  message.getMessageProperties().getHeaders().put("test2", "test222");
  return message;
  }
});

简单案列‼️

依赖

<-- rabbitMQ 依赖 -->
<dependency>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-amqpartifactId>
dependency>
<-- 引入rabbitTemplate  -->  
<dependency>
  <groupId>com.rabbitmqgroupId>
  <artifactId>amqp-clientartifactId>
  <version>3.6.5version>
dependency>  
spring:
  rabbitmq:
    host: 119.91.00.00
    port: 5672
    username: admin
    password: admin
    virtual-host: my

配置文件

  1. 创建交换机
  2. 创建队列
  3. 绑定交换机和队列
package com.imooc.api.config;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author LFweixiao
 * @create 2022-04-06 8:11 下午
 */
@Configuration
public class RabbitMQConfig {

    //定义交换机名称
    public static final String EXCHANGE_ARTICLE = "exchange_article";

    //定义队列名称
    public static final String QUEUE_DOWNLOAD_HTML = "queue_download_html";

    //创建交换机,放入springboot 容器
    @Bean(EXCHANGE_ARTICLE)
    public Exchange exchange() {
        return ExchangeBuilder  //构建交换机
                .topicExchange(EXCHANGE_ARTICLE)  //使用 topic 类型交换机
                .durable(true)     //设置持久化,重启MQ后依然存在
                .build();
    }

    //创建队列
    @Bean(QUEUE_DOWNLOAD_HTML)
    public Queue queue(){
        return new Queue(QUEUE_DOWNLOAD_HTML);
    }

    //队列绑定交换机
    @Bean
    public Binding binding(
            @Qualifier(QUEUE_DOWNLOAD_HTML) Queue queue,
            @Qualifier(EXCHANGE_ARTICLE) Exchange exchange
    ) {
        return BindingBuilder  //定义绑定关系
                .bind(queue)    //绑定队列
                .to(exchange)   //绑定交换机
                .with("article.*")  //定义路由规则(requestMapping 映射)
                .noargs();  //执行绑定
    }


}

发送消息

public class{
  
      @GetMapping("hello1")
    public Object hello1() {
        // 往 EXCHANGE_ARTICLE 发送一条消息,并且指定相应的路由规则
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.EXCHANGE_ARTICLE   //绑定 交换机
                ,"article.download"     // 路由 routingKey
                ,"发送消息"     //消息体
        );
      return "ok";
}

监听消息

@Component
public class RabbitMQConsumer {
    /**
     * 监听MQ 消息队列
     * @param payload 消息内容
     * @param message 消息对象
     */
    @RabbitListener(queues = {RabbitMQConfig.QUEUE_DOWNLOAD_HTML})
    public void watchQueue(String payload, Message message) {
        //System.out.println(payload);
        //获取消息 路径
        String routingKey = message.getMessageProperties().getReceivedRoutingKey();
        if (routingKey.equalsIgnoreCase("article.download")) {
            //业务处理
        }else if(routingKey.equalsIgnoreCase("article.download.do")){
            //业务处理
        }else {
            //业务处理
        }
    }
}

延迟队列

需要安装x-delayed-message

配置类

@Configuration
public class RabbitMQDelayConfig {
    // 定义交换机的名称
    public static final String EXCHANGE_DELAY = "exchange_delay";

    // 定义队列的名称
    public static final String QUEUE_DELAY = "queue_delay";

    //创建 延迟队列交换机
    @Bean(EXCHANGE_DELAY)
    public Exchange exchange(){
        return ExchangeBuilder
                .topicExchange(EXCHANGE_DELAY) //构建 topic 类型
                .durable(true) //持久化
                .delayed()   // 设置为延迟队列
                .build();  //构建
    }

    // 创建队列
    @Bean(QUEUE_DELAY)
    public Queue queue() {
        return new Queue(QUEUE_DELAY);
    }

    // 队列绑定交换机
    @Bean
    public Binding delayBinding(
            @Qualifier(QUEUE_DELAY) Queue queue,
            @Qualifier(EXCHANGE_DELAY) Exchange exchange) {
        return BindingBuilder               // 定义绑定关系
                .bind(queue)                // 绑定队列
                .to(exchange)               // 到交换机
                .with("delay.*")   // 定义路由规则(requestMapping映射)
                .noargs();                  // 执行绑定
    }
}

发送消息

注意: 此处idea 自动导入的包是错误的,正确的包是

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
@GetMapping("mq02")
    public Object mq02() {
        
        MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                // 设置持久
                message.getMessageProperties()
                        .setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                // 设置延迟的时间,单位毫秒
                message.getMessageProperties().setDelay(5000);
                return message;
            }
        };

        rabbitTemplate.convertAndSend(
                RabbitMQDelayConfig.EXCHANGE_DELAY  //延迟队列 绑定交换机
                ,"delay.test"    //路由 routingKey
                ,"延迟队列消息"
                ,messagePostProcessor
        );
        return "ok";
    }

底部

你可能感兴趣的:(mq,rabbitmq)