day01-RabbitMQ_2026-05-13

RabbitMQ

MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是异步调用中的Broker。

📌技术对比

🚀 特性 🐇 RabbitMQ 🔺 ActiveMQ 🚀 RocketMQ 🖧 Kafka
🏢 公司/社区 Rabbit Apache 阿里 Apache
💻 开发语言 Erlang Java Java Scala & Java
📜 协议支持 AMQP, XMPP, SMTP, STOMP OpenWire, STOMP, REST, XMPP, AMQP 自定义协议 自定义协议
✅ 可用性 一般
📊 单机吞吐量 一般 非常高
⏱ 消息延迟 微秒级 毫秒级 毫秒级 毫秒以内
🔒 消息可靠性 一般 一般

RabbitMQ的整体架构及核心概念:

  • virtual-host:虚拟主机,起到数据隔离的作用

  • publisher: 消息发送者

  • consumer:消息的消费者

  • queue:队列,存储消息

  • exchange:交换机,负责路由消息

🏷Java客户端

📘快速入门

  1. 引入spring-amqp依赖

在父工程中引入spring-amqp依赖,这样publisher和consumer服务都可以使用:

xml 复制代码
<!-- AMQP依赖,包含RabbitMQ -- >
<dependency>
  <groupId>org. springframework. bootk/groupId>
  <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  1. 配置RabbitMQ服务端信息

在每个微服务中引入MQ服务端信息,这样微服务才能连接到RabbitMQ

xml 复制代码
spring:
  rabbitmq:
    host: 192.168.228.129 #主机
    port: 5672 #端口
    username: dengwuguang #账号
    password: 1234 #密码
    virtual-host: /dwg #虚拟主机
  1. 发送消息

SpringAMQP提供了RabbitTemplate工具类,方便我们发送消息。发送消息代码如下:

java 复制代码
@SpringBootTest
public class SpringAMQPTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSendMessage() {
        //指定队列
        String queueName = "simple.queue";
        // 1.指定消息内容
        String message = "Hello World !";
        // 2.发送消息
        rabbitTemplate.convertAndSend(queueName, message);
    }
}
  1. 接收消息

SpringAMQP提供声明式的消息监听,我们只需要通过注解在方法上声明要监听的队列名称,将来

SpringAMQP就会把消息传递给当前方法:

java 复制代码
@Slf4j
@Component
public class Mqlistener {

    @RabbitListener(queues = "simple.queue")// 监听simple.queue队列
    public void listenSimplequeue(String  message){
        System.out.println("消费者接收到的消息是:"+message);
    }
}

SpringAMQP如何收发消息?

  1. 引入spring-boot-starter-amqp依赖

  2. 配置rabbitmq服务端信息

  3. 利用RabbitTemplate发送消息

  4. 利用@RabbitListener注解声明要监听的队列,监听消息


📘Work Queues

📌消费者消息推送限制

默认情况下,RabbitMQ的会将消息依次轮询投递给绑定在队列上的每一个消费者。但这并没有考虑到消费者是否已经

处理完消息,可能出现消息堆积。

因此我们需要修改application.yml,设置preFetch值为1,确保同一时刻最多投递给消费者1条消息:

xml 复制代码
spring:
  rabbitmq:
    listener:
      simple:
        prefetch:1 # 每次只能获取一条消息,处理完成才能获取下一个消息

Work模型的使用:

  • 多个消费者绑定到一个队列,可以加快消息处理速度

  • 同一条消息只会被一个消费者处理

  • 通过设置prefetch来控制消费者预取的消息数量,处理完一条再处理下一条,实现能者多劳


📘Fanout交换机

Fanout Exchange会将接收到的消息广播到每一个跟其绑定的queue,所以也叫广播模式

📌步骤

  1. 编写消息监听器,监听fanout.queue1和fanout.queue2

    • 在consumer服务的SpringRabbitListener类中,添加两个方法,分别监听fanout.queue1和fanout.queue2:
    java 复制代码
    @RabbitListener(queues = "fanout.queue1")// 监听simple.queue队列
    public void listenFanoutqueue1(String message) {
        System.out.println("消费者listenFanoutqueue1接收到的消息是:" + message);
    }
    
    @RabbitListener(queues = "fanout.queue2")// 监听simple.queue队列
    public void listenFanoutqueue2(String message) {
        System.out.println("消费者listenFanoutqueue2接收到的消息是:" + message);
    }
  2. 编写单元测试,向dwg.fanout交换机发送消息

    • 在publisher服务的SpringAmqpTest类中添加测试方法:
    java 复制代码
    @Test
     public void testSendFanout() {
         //指定队列
         String ExchangeName = "dwg.fanout";
         // 1.指定消息内容
         String message = "Hello everyone !";
         // 2.发送消息
         rabbitTemplate.convertAndSend(ExchangeName, null,message);
     }

交换机的作用是什么?

  • 接收publisher发送的消息

  • 将消息按照规则路由到与之绑定的队列

  • FanoutExchange的会将消息路由到每个绑定的队列


📘Direct交换机

Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由。

  • 每一个Queue都与Exchange设置一个BindingKey
  • 发布者发送消息时,指定消息的RoutingKey
  • Exchange将消息路由到BindingKey与消息RoutingKey一致的队列

步骤:

  1. 编写消息监听器,监听direct.queue1和direct.queue2

    • 在consumer服务的SpringRabbitListener类中,添加两个方法,分别监听direct.queue1和direct.queue2:
    java 复制代码
    @RabbitListener(queues = "direct.queue1")// 监听simple.queue队列
    public void listenDirectqueue1(String message) {
        System.out.println("消费者listenDirectqueue1接收到的消息是:" + message);
    }
    
    @RabbitListener(queues = "direct.queue2")// 监听simple.queue队列
    public void listenDirectqueue2(String message) {
        System.out.println("消费者listenDirectqueue2接收到的消息是:" + message);
    }
    1. 编写单元测试,向dwg.direct交换机发送消息
    • 在publisher服务的SpringAmqpTest类中添加测试方法:
    java 复制代码
    @Test
     public void testSendDirect() {
         //指定队列
         String ExchangeName = "dwg.direct";
         // 1.指定消息内容
         String message = "Hello !";
         // 2.发送消息
         rabbitTemplate.convertAndSend(ExchangeName, "blue",message);
     }

📘Topic交换机

TopicExchange与DirectExchange类似,区别在于routingKey可以是多个单词的列表,并且以.分割。

Queue与Exchange指定BindingKey时可以使用通配符:

  • #:代指0个或多个单词

  • *: 代指一个单词

描述下Direct交换机与Topic交换机的差异?

  • Topic交换机接收的消息RoutingKey可以是多个单词,以.分割

  • Topic交换机与队列绑定时的bindingKey可以指定通配符

    • #:代表0个或多个词

    • *: 代表1个词


📘声明队列和交换机

SpringAMQP提供了几个类,用来声明队列、交换机及其绑定关系:

  • Queue:用于声明队列,可以用工厂类QueueBuilder构建

  • Exchange:用于声明交换机,可以用工厂类ExchangeBuilder构建

  • Binding:用于声明队列和交换机的绑定关系,可以用工厂类BindingBuilder构建

方式1:

java 复制代码
@Configuration
public class FanoutConfig {

    @Bean
    public FanoutExchange fanoutExchange(){
        //声明交换机
        return new FanoutExchange("dwg.fanout1");
    }

    @Bean
    public Queue Queue(){
        //声明队列
        return new Queue("fanout.queue3");
    }

    @Bean
    public Binding fanoutBinding(){
        //绑定关系
        return BindingBuilder.bind(Queue()).to(fanoutExchange());
    }
}

SpringAMQP还提供了基于@RabbitListener注解来声明队列和交换机的方式:

方式2:

java 复制代码
@RabbitListener(bindings = @QueueBinding(
      value = @Queue(name = "direct.queue1"),
      exchange = @Exchange(name = "itcast.direct", type = ExchangeTypes.DIRECT),
      key = {"red", "blue"}
)
public void listenDirectQueue1(String msg) {
  System.out.println("消费者1接收到Direct消息:【"+msg+"】");
}

📘消息转换器

建议采用JSON序列化代替默认的JDK序列化,要做两件事情:

在publisher和consumer中都要引入jackson依赖:

xml 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

在publisher和consumer中都要配置MessageConverter:

java 复制代码
@Bean
public MessageConverter jacksonMessageConvertor(){
    return new Jackson2JsonMessageConverter();
}

🧾总结:今天学习了RabbitMQ的基础部分,因为之前有使用基于stream的消息队列的经验,所以学起来比较轻松,明天学完RabbitMQ的高级部分,加油!🔥🔥🔥

相关推荐
cheems95272 小时前
[RabbitMQ] RabbitMQ 工作流程全解析
分布式·rabbitmq
我只想困告4 小时前
day02-RabbitMQ 2026-05-14
java·spring·rabbitmq
敖正炀4 小时前
读写分离与数据库中间件选型
分布式
Mahir085 小时前
Redis 分布式锁与 Redisson 深度解析:从原生实现到工业级解决方案
数据库·redis·分布式·缓存·面试
敖正炀5 小时前
分布式事务监控与手动恢复平台设计
分布式
逆境不可逃6 小时前
Hello-Agents 第二部分-第四章总结:智能体经典范式构建-包含习题解析和Java版
java·开发语言·javascript·人工智能·分布式·agent
heimeiyingwang6 小时前
【架构实战】RocketMQ实战:分布式消息中间件
分布式·架构·rocketmq
报错小能手6 小时前
分布式讲解—分布式事务解决方案 刚性(2PC、3PC、XA协议)
分布式
heimeiyingwang6 小时前
【架构实战】RabbitMQ实战:企业级消息可靠传递
架构·rabbitmq·ruby