最新RabbitMQ教程【2023】

RabbitMQ

本文介绍了JMS的方式去操作MQ,帮助大家更快了解RabbitMQ。

同时主要使用Springboot的方去教学,帮助大家快速的开发。

本文章是详细介绍RabbitMQ使用的一篇文章,博主总结了CSDN上面两个大佬的文章和黑马程序员的视频。

第一个文章:RabbitMQ快速入门 这一篇文章是采用的JMS的方式来操作RabbitMQ,JMS类似于JDBC,对我们熟悉RabbitMQ有很大的帮助。

第二个文章:RabbitMQ详解,用心看完这一篇就够了 这一篇文章主要是采用SpringBoot 的方式进行演示代码,对实际开发很有帮助。

 

消息队列

        消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。

        消息队列是一种应用间的异步协作机制,同时消息队列中间件是分布式系统中重要的组件,主要解决应用耦合异步消息流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。

RabbitMQ

        RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现,官网地址:http://www.rabbitmq.com。RabbitMQ作为一个消息代理,主要负责接收、存储和转发消息,它提供了可靠的消息机制和灵活的消息路由,并支持消息集群和分布式部署,常用于应用解耦,耗时任务队列,流量削锋等场景。

        首先,了解RabbitMQ首先要了解一下JMSAMQP是什么?

JMS

        JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。

        JMS就是API,就相当于JDBC,JDBC我们都知道是Java操作关系型数据库的API(最原始的开发就是使用JDBC来完成数据库的增删改查。而JMS就是Java操作MQ的API,现在大多消息队列都实现了这个东西,都能用Java的方式去操作它。

AMQP

        JMQP(advanced message queuing protocol)是一种协议,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。这使得实现了AMQP的provider天然性就是跨平台的。

        什么意思,协议就是规定了你该怎么做,但是并不在意你的细节。我们可以参考HTTP协议,HTTP只是一个协议,但是你可以通过Java来实现他,也可以使用python做为web程序的后端。

AMQP就是规定了MQ该怎么传输的协议,例如RabbitMQ就是实现了这个协议的一个产品。

 

简单来说:RabbitMQ实现了AMQP协议,然后我们可以通过JMS去操作它

 

原理介绍

我们幻想一个场景,我们自己要来实现一个消息队列,应该怎么设计呢?

最简单的方式,就是我们放一个队列在这里,然后生产者放消息,消费者拿消息。

4384ea9fd3654a11899f9274e70996c9.png

 

        但是这样会有一个问题,只有一个队列,只能放置一种消息,如果消息种类多了岂不是不行了。所以我们进行改造:让生产者和消费者直接有多个队列

 

fcf7a31466584068b0a73c7555f3f223.png        然后又出现一个问题,生产者放置消息的时候,怎么知道放在哪个队列呢?如果队列很多,那么我放置消息的时候是不是要一一对应每一个消息队列去放置。

        所以我们在生产者和队列之间增加一个交换机Exchange,然后让交换机跟队列产生绑定binding我只管给交换机发送消息,然后交换机通过跟队列的binding自行将消息放到队列中去。

4faa640d93b14e1899c6365587b0dd90.png

 

        但是又出现了问题,如果我们编程实现了上面的设计,那么一个模型只有一个交换机,每个业务都要单独启动用一个这个模型,所以我们希望自己设计的MQ要高效一点,要通用一点。

d8c69f5b6b074152a41a9d2b309bbdba.png

 

        所以我们增加了一个概念,叫虚拟主机Virtual host ,这个虚拟主机就是用来逻辑上面隔离的。一个虚拟主机中能有多个交换机,然后每个主机之间是互相不干扰的。现在多个业务就能同时使用我们设计的模型了

 

以上就是RabbitMQ的简单模型:

  • Publisher:消息发送者,将消息发送到Exchange并指定RoutingKey,以便queue可以接收到指定的消息。

  • Consumer:消息消费者,从queue获取消息,一个Consumer可以订阅多个queue以从多个queue中接收消息。

  • Server:一个具体的MQ服务实例,也称为Broker。

  • Virtual host:虚拟主机,一个Server下可以有多个虚拟主机,用于隔离不同项目,一个Virtualhost通常包含多个Exchange、Message Queue。

  • Exchange:交换器,接收Producer发送来的消息,把消息转发到对应的Message Queue中。

  • Message Queue:实际存储消息的容器,并把消息传递给最终的Consumer。

 

 

RabbitMQ的安装

这里直接跳过,我们引入其他博主的文章,都是最简单的安装(一直下一步)

超详细!!!Windows下安装RabbitMQ的步骤详解

安装成功后记得回来

rabbitMQ的使用

RabbitMQ有管理页面,和代码操作的使用

管理页面稍微点两下,就能清楚怎么操作,我们着重讲代码使用

RabbitMQ管理页面介绍

安装好后,RabbitMQ是开机默认启动的,所以我们打开RabbitMQ的管理页面:http://localhost:15672/,默认的账号和密码都是guest。

593e0b5bd7f54ca7915fc4f30bc8e331.png

 

可以看到管理页面上面有几个分类:

1)OverView:有RabbitMQ的一些基本信息

2)Connection:链接,不管是消费者还是生产者,都会跟RabbitMQ产生链接

3)Channel:通道,产生链接之后,要发送消息和接受消息,需要建立通道

4)Exchanges:交换机,点进去可以看到有多种类型的交换机(直连交换机、主题交换机等)

5)Queues:队列,就是运行时候的真正的消息队列

6)Admin:管理,可以管理用户、管理虚拟主机、管理集群等。

 

这里是关于用户和虚拟主机的创建的截图,一般是创建一个用户,然后分配虚拟主机,然后再进行使用。

2d21c94a2aa648308a91929505d652c0.png

RabbitMQ的消息模型

详情可见官方文档的入门文档:RabbitMQ Tutorials — RabbitMQ

主要就是分为如下的五种,这里你们只需要记住有这五种就行了,后面我会一一带领大家去操作

1)基本消息模型工作消息模型:都是直接基于消息队列的方式进行发送和接受消息的

2)基于发布订阅模式:广播消息模型、路由消息模型、主题消息模型

 

入门代码——基本消消息模型

这里我们导入依赖,来进行MQ的操作

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.7.1</version>
</dependency>

流程是:

1)创建链接connection

2)通过连接获取通道channel

3)使用通道声明队列

注意:消费者和生产者的前三步都是一样的

4)生产消息/消费消息

 

生产者代码

值得注意的是,发送的消息要求是字节的形式,所以在发送消息的时候要转化为字节

@Test
public void testSendMessage() throws IOException, TimeoutException {
​
    //1.1创建链接工厂
    ConnectionFactory factory = new ConnectionFactory();
​
    //1.2设置信息
    factory.setHost("localhost");//RabbitMQ的ip地址
    factory.setPort(5672);//端口地址
    factory.setVirtualHost("/");//虚拟主机(可以在管理页面创建)
    factory.setUsername("guest");//用户名和密码:也可以在管理页面创建
    factory.setPassword("guest");
​
    //1.3获取链接
    Connection connection = factory.newConnection();
​
    //2获取通道
    Channel channel = connection.createChannel();
​
    //3创建队列
    /**
         * 参数明细
         * 1、queue 队列名称
         * 2、durable 是否持久化,如果持久化,mq重启后队列还在
         * 3、exclusive 是否独占连接,队列只允许在该连接中访问,如果connection连接关闭队列则自动删除,如果将此参数设置true可用于临时队列的创建
         * 4、autoDelete 自动删除,队列不再使用时是否自动删除此队列,如果将此参数和exclusive参数设置为true就可以实现临时队列(队列不用了就自动删除)
         * 5、arguments 参数,可以设置一个队列的扩展参数,比如:可设置存活时间
         */
    channel.queueDeclare("simple.queue", false, false, false, null);
​
    //4发送消息
    String message = "hello";
        /**
         * basicPublish()方法参数明细:
         * 1、exchange,交换机,如果不指定将使用mq的默认交换机(设置为"")
         * 2、routingKey,路由key,交换机根据路由key来将消息转发到指定的队列,如果使用默认交换机,routingKey设置为队列的名称
         * 3、props,消息的属性
         * 4、body,消息内容
         */
    channel.basicPublish("","simple.queue",null,message.getBytes(StandardCharsets.UTF_8));
​
    System.out.println("消息发送成功:"+message);
​
    //5关闭通道和链接
    channel.close();
    connection.close();
}

 

运行程序之后:可以看到已经有了一条消息

94513a742acb492fab44a12a7967b946.png

 

消费者代码

消费者进行消费消息,主要是依靠DefaultConsumer这个类实现的,所以我们使用匿名内部类的方式进行消息的消费

@Test
public void testConsumeMessage() throws IOException, TimeoutException {
    //1.1创建链接工厂
    ConnectionFactory factory = new ConnectionFactory();
​
    //1.2设置信息
    factory.setHost("localhost");//RabbitMQ的ip地址
    factory.setPort(5672);//端口地址
    factory.setVirtualHost("/");//虚拟主机(可以在管理页面创建)
    factory.setUsername("guest");//用户名和密码:也可以在管理页面创建
    factory.setPassword("guest");
​
    //1.3获取链接
    Connection connection = factory.newConnection();
​
    //2获取通道
    Channel channel = connection.createChannel();
​
    //3创建队列
    channel.queueDeclare("simple.queue", false, false, false, null);
​
​
    //4消费消息
        /**
         * basicConsume()方法参数明细
         * 1.消息队列的名字(要跟发送方保持一样)
         * 2.是否是自动确认机制:ACK机制,选择true进行自动确认
         * 3.怎么消费这个消息:用匿名内部类的方式实现
         */
    channel.basicConsume("simple.queue",true,new DefaultConsumer(channel){
        @Override
        public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
            String message = new String(body);
​
            System.out.println("收到的消息是:"+message);
        }
    });
​
}

 

消息已经被消费了

114067608ce64b45a9f15e8fc240bad9.png

 

        入门案例就是典型的JMS实现方式。我们可以借助JDBC来进行理解,例如:我们在操作MySql的时候,也是先获取连接工厂、获取连接、获取操作数据库的对象、进行操作。而这里也是差不多的形式:获取连接工厂、创建连接、获取通道、定义队列、消息操作。简直是一模一样的流程。

        但是,可以看到入门案例过程十分繁琐,每次我都要重复操作一些东西就很浪费时间,做了跟业务无关的操作这个是得不偿失的。就像操作数据库一样,Spring也给我们准备了关于消息队列的模板AMQP。

 

Spring—AMQP

Spring AMQP是基于AMQP协议定义的一套API规范,提供了模板来进行发送接收消息。

就像我们使用redisTemplate一样,定义好了模板。然后实现Springt-AMQP的就是Spring-Rabbit。

来自官网的介绍

Features:

  • Listener container for asynchronous processing of inbound messages

  • RabbitTemplate for sending and receiving messages

  • RabbitAdmin for automatically declaring queues, exchanges and bindings

 

翻译过来就是,SpringAMQP具有的特点有:

  • 用于异步处理入站消息的侦听器容器

    就是一直在监听,有消息就消费,没有就继续监听,方便得很

  • RabbitTemplate发送和接收消息的模板

    之前发送和接收消息,需要我们手动去转成字节,手动去发送和接收,烦的一

  • RabbitAdmin,用于自动声明队列交换和绑定

    以前声明队列都是我们手动去生成的,特别不方便

 

简单队列

我们来实现刚刚的入门案例,用Spring的方式实现:简单队列模式

我们依旧使用上面例子中的队列名:simple.queue

一、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

二、编写yml配置

这里我们生产者和消费者都配置一样的参数

spring:
  rabbitmq:
    host: localhost #主机名
    port: 5672 #MQ的端口号
    virtual-host: / #虚拟主机名
    username: guest
    password: guest

三、创建队列

我们创建一个配置类来进行队列的创建

注意:如果创建不成功,是因为入门代码那边已经创建了一个simple.queue队列,请先删除再创建

@Configuration
public class QueueConfiguration {
    @Bean
    public Queue simpleQueue(){
        return new Queue("simple.queue");//队列的名字
    }
}

四、使用RabbitTemplate发送消息

只需要调用rabbitTemplate.convertAndSend方法,就能够成功发送消息了

@SpringBootTest
public class testProvider {
​
    @Autowired
    RabbitTemplate rabbitTemplate;
​
    @Test
    public void testSendMessage(){
        String queueName = "test.queue";
        String message = "我在学习RabbitMQ";
        rabbitTemplate.convertAndSend(queueName,message);
    }
}

五、客户端接收消息

定义一个类,然后使用注解的方式来进行监听消息,真实开发场景可以定义成一个Service

@Service
public class MessageListener {
​
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueueMessage(String message){
        System.out.println("收到的消息是:"+message);
    }
}

然后启动我们的springboot项目,因为这个是监听,所以要一直启动状态

五、测试基本消息队列

1)发送方一直发送消息

2)查看消费方的控制台

a6d18f2b8d174336aeafb166936bb491.png

 

发送Object对象

我们发送消息,不仅仅能够发送String类型,还能发送任意对象,SpringAMQP会帮我们自动转换。

注意:传递的对象一定要实现Serializable接口

我们这里创建一个object.queue的队列,然后给他发送Person对象,再监听输出

@Bean
public Queue ObjectQueue(){
    return new Queue("object.queue");
}
@Test
public void testSendObject(){
    Person person = new Person();
    person.setName("black_pp");
    person.setSex("boy");
    person.setAge("永远18岁");
​
    rabbitTemplate.convertAndSend("object.queue",person);
}
@RabbitListener(queues = "object.queue")
public void listenObject(Person person){
    System.out.println("收到的对象是:"+person);
}

测试,对象成功的转发了:

c8c92f98d8744f089aac953cd4d15d6c.png

 

消息转换器

        上面传递的对象实际上在RabbitMQ中表现形式是这种的,一个小小的对象,要占用很多字符,所以我们这里可以使用JSON的格式来序列化对象。

3d74585a28a44bf6aae6ae2957ed59b4.png

        我们需要重新配置一个消息转换器(发送方和接收方都需要配置),这里配置的是JSON格式的消息转换器。

@Bean
public MessageConverter messageConverter(){
    return new Jackson2JsonMessageConverter();
}

        这时候,我们在发送和接收对象类型,就不需要实现Serializable接口了,并且在RabbitMQ中的表现形式也是JSON的格式,非常的友好。

739aedd1ea8347878e648e01f458ce1b.png

 

工作队列

 

工作队列就是消费者不止一个,众多消费者之间是合作关系;假如消息发送者,每秒有50条消息,但是一个消费者每秒只能消费30条消息,这就需要多个消费者构成一个工作队列了。能提高消息消费的速度。

612d86a7d0504c69b20486770dd38fb9.png

 

我们改造一下发送方的代码:让他一秒发50条数据

@Test
public void testWorkQueue() throws InterruptedException {
    String queueName = "simple.queue";
    for (int i = 1; i <= 50; i++) {
        rabbitTemplate.convertAndSend(queueName,"这是第 "+i+" 条消息");
        Thread.sleep(20);//每次休息20秒,总共50次,正好是一秒50条消息
    }
}

然后在消费者这边,定义两个监听来模拟有多个消费者

@Service
public class MessageListener {
​
    private static int numA = 0;
    private static int numB = 0;
​
    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueueA(String message) throws InterruptedException {
        numA++;
        System.out.println("【A】收到的消息是:"+message+",已经消费的数量是:"+numA);
    }
​
    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueueB(String message) throws InterruptedException {
        numB++;
        System.err.println("【B】收到的消息是:"+message+",已经消费的数量是:"+numB);
    }
}

最后的结果是:两个消费者轮流进行消费

72c1ba6f9a884d41ba82d04a449a9d33.png

但是我们希望的是,谁消费更快,谁拿更多的消息,不采用这种方式,那该怎么办呢?

 

消费预取机制

这个机制就是说,在我们消费者消费之前,我们进行预先轮流取消息,然后再消费

例如:

A在真正消费之前,就开始取消息:1、3、5、7、9....

B在真正消费之前,也开始同时取消息:2、4、6、8....

        

这样就是说,我还没开始消费,就已经预定了,所以不管我消费速度如何,这些消息都是我来消费

改进方案

        怎么解决这个问题呢?让消息处理更快的拿去到更多的消费信息,我们可以将消费预取的长度设置为1

        两个消费者预取到一条数据之后,就开始执行,执行完毕又再取一条数据,这样就是谁执行越快,取到的消息越多。

 

1)我们在消费者这边,让A和B每次执行之后都休眠

A休眠50毫秒,一秒大概能消费20条数据

B休眠30毫秒,一秒大概能消费30条数据左右

@RabbitListener(queues = "simple.queue")
public void listenWorkQueueA(String message) throws InterruptedException {
    numA++;
    System.out.println("【A】收到的消息是:"+message+",已经消费的数量是:"+numA);
    Thread.sleep(30);
}
​
@RabbitListener(queues = "simple.queue")
public void listenWorkQueueB(String message) throws InterruptedException {
    numB++;
    System.err.println("【B】收到的消息是:"+message+",已经消费的数量是:"+numB);
    Thread.sleep(50);
}

2)在消费者这边,修改application.yml文件

添加:listener.simple.prefetch = 1

spring:
  rabbitmq:
    host: localhost #主机名
    port: 5672 #MQ的端口号
    virtual-host: / #虚拟主机名
    username: guest
    password: guest
    listener:
      simple:
        prefetch: 1 #每次只预先取一个数据

3)测试结果:消费能力快的,消费得更多

96b3fdd893654d6b8b9fcd5c9a36a025.png

 

 

发布订阅模式

        之前的案例中,我们的消息是什么被消费了,就删除了。消息A消费了一个消息,那个消息就被直接删除了,如果B也想消费那个消息,显然是做不到了的。

        想象一个例子:我们购买了一个商品,然后订单消息会发送给:物流系统、商家平台等。如果使用之前的模式,那么物流系统拿到订单消息之后,直接把消息删除了,商家就拿不到该订单的消息了,那商家就不能进行发货处理。

所以我们得使用发布——订阅模式

e89491576f624d81bd3374775eea41b2.png

 

        这里假设consumer1和consumer2都是物流系统,consumer3是商家系统,只要同时给这两个队列发送相同的消息,就能解决上面的问题。实现的方式就是加上交换机

交换机有多个种类:

  • fanout:广播交换机

  • direct:路由交换机

  • topic:话题交换机

广播交换机

        FanoutExchange—广播交换机:会把自己接收到的每一条消息,都转发给所有跟自己绑定的消息队列。

        实现的思路就是:创建队列、创建交换机、给他们进行绑定,然后就是消费者监听,生产者发送。

一、创建交换机和队列并进行绑定

        这里我们在消费者中创建配置类:FanoutConfiguration,然后再配置类中使用@Bean注解生成需要的队列和交换机等

注意:这里Queue的类型是:org.springframework.amqp.core.Queue;

@Configuration
public class FanoutConfiguration {
​
    /**
     *创建交换机对象,取名叫:test.fanout
     */
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("test.fanout");
    }
​
    /**
     *创建两个队列
     */
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
​
    /**
     * 创建绑定对象:分别绑定交换机跟队列
     */
    @Bean
    public Binding binding1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    @Bean
    public Binding binding2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
​
}

二、更改发送方

之前我们使用RabbitTemplate的时候传参是队列名称和消息

现在我们传参变为:交换机名称、路由键、消息

  • 因为我们现在是发消息给交换机了,所以我们这边需要交换机名字(刚刚配置文件中的名字)

  • 因为这是广播的方式,所以不需要路由,中间那个参数填空字符串就行(RabbitMQ遵循默认的规则)

@Test
public void testFanoutExchange() throws InterruptedException {
    String exchangeName = "test.fanout";
    String message = "hello,fanoutExchange";
    
    rabbitTemplate.convertAndSend(exchangeName,"",message);
}

三、编写接收方

接收方和之前的代码并没有区别,只是监听的队列变了

@RabbitListener(queues = "fanout.queue1")
public void listenFanout1(String message){
    System.out.println("从队列fanout.queue1中拿到消息:"+message);
}
@RabbitListener(queues = "fanout.queue2")
public void listenFanout2(String message){
    System.out.println("从队列fanout.queue2中拿到消息:"+message);
}

测试:发送方发送一条消息,结果两个客户端都收到了同一个消息

0fdaad15af9e44d784cf6b3de3d065aa.png

 

 

路由交换机

路由交换机,顾名思义就是能够对消息进行路由,交换机会根据一个值,把消息路由到指定的队列中去

4828af05971d4521aabb7dd3fc64eb3a.png

 

执行流程是:

1)你发送消息给交换机,并指定路由的key

2)如果key的值是cat,交换机则转发到queue1;如果是dog,交换机则转发到queue2。

 

注意:如果key值相等,那么两个队列都会收到消息。

 

一、创建交换机和队列,并绑定

在广播交换机的时候,我们使用配置类的方式来声明交换机、队列、绑定关系。

这里我们直接在消费端的 @RabbitListener 注解中完成上面的任务,进一步方便开发。

 

注意:一个队列可以指定多个路由key

    /**
     *  1.在RabbitListener中指定bindings属性
     *  2.在QueueBinding中指定,要绑定的交换机、队列、和key
     */
@RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(name = "direct.queue1"),
                exchange = @Exchange(name = "directExchange",type = ExchangeTypes.DIRECT),
                key = "cat"
        )
)
public void listenDirect1(String message){
    System.out.println("从队列路由key为cat的队列中拿到消息:"+message);
}

二、发送方发送消息,指定路由key

@Test
public void testFanoutExchange() throws InterruptedException {
    String exchangeName = "directExchange";
    String message = "hello,fanoutExchange";
​
    rabbitTemplate.convertAndSend(exchangeName,"cat",message);
}

测试结果:指定路由规则之后,正常接收到消息

8dc28170b507423bad6cb241f43c9e98.png

 

话题交换机

话题交换机跟上面的路由交换机是一样的,路由的时候都指定一个路由key,然后进行路由。

特点:

  • 话题交换机的路由key是用.分割的

    例如:xxx.xxx 的形式

  • 话题交换机支持通配符

    #代表0个或者多个单词

    *代表一个单词

例如:

用 user.#代表路由key,就能匹配所有user开头的队列。

用#.log表示路由key,就能匹配所有跟日志相关的队列。

 

一、声明交换机、队列和绑定关系

还是跟上面一样,在消费端直接使用注解来声明

@RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(name = "topic.queue1"),
                exchange = @Exchange(name = "topic.exchange",type = ExchangeTypes.TOPIC),
                key = "user.#"
        )
)
public void listenTopic1(String message){
    System.out.println("收到关于user的话题消息:"+message);
}

二、发送方发送消息

发送方发送两个消息,一个路由key是user.active,一个key是user.order

@Test
public void testFanoutExchange() throws InterruptedException {
    String exchangeName = "topic.exchange";
    String message = "用户的订单";
​
    rabbitTemplate.convertAndSend(exchangeName,"user.order",message);
}

测试:发送两个不同的路由key,但是都能接收到

30e2de7671a345ffb0852cf907f31af9.png

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值