秒懂 RabbitMQ!5 大工作模型像 “快递配送”,3 种声明方式直接用

153 阅读7分钟

家人们!咱用 RabbitMQ 时,是不是总被 “工作模型”“交换机绑定” 整懵?其实这些模型本质就是 “不同的消息配送方案”—— 今天用 “快递配送” 的日常场景,把 5 大模型嚼碎,再手把手教你 3 种声明方式,看完直接复制代码上手!

一、先搞懂核心:RabbitMQ 工作模型 =“快递配送方案”

RabbitMQ 的所有工作模型,都围绕 “交换机(分拣站)+ 队列(快递柜)+ 生产者(寄件人)+ 消费者(收件人)” 这四件套。不同模型,就是 “分拣站怎么把快递分到快递柜” 的不同规则 —— 咱逐个看:

image.png

1. Basic Queue:简单模式 =“个人寄快递,一对一送”

类比场景

你给朋友寄一箱零食,直接写朋友地址,快递员只送这一个收件人 ——一个生产者发消息,一个消费者收消息,一对一专属配送

原理拆解

  • 没有复杂交换机!生产者直接把消息扔到 “Basic Queue” 队列;
  • 消费者盯着这个队列,消息一到就拿走处理;
  • 特点:简单直接,适合 “单一任务处理”(比如下单后发一条短信通知)。

代码小片段(SpringAMQP)

// 生产者发消息(直接指定队列名)
@GetMapping("/send-simple")
public String sendSimple() {
    rabbitTemplate.convertAndSend("basic-queue", "这是简单模式的消息~");
    return "消息发送成功!";
}
// 消费者收消息(监听指定队列)
@RabbitListener(queues = "basic-queue")
public void receiveSimple(String msg) {
    System.out.println("收到简单模式消息:" + msg);
}

2. 广播模式(Publish/Subscribe)=“小区群发通知,人人有份”

类比场景

小区物业发 “停水通知”,所有业主都要收到 ——一个生产者发消息,多个消费者同时收到,消息像广播一样扩散

原理拆解

image.png
  • 必须用 “Fanout 交换机”(像小区公告栏,贴上去的通知所有人能看);
  • 所有队列都绑定到这个 Fanout 交换机;
  • 生产者把消息发给 Fanout 交换机,交换机会把消息 “复制” 到所有绑定的队列,每个消费者都能拿到完整消息;
  • 特点:消息不重复,每个消费者都能收到,适合 “群发通知”(比如系统维护通知、订单状态同步给多个下游系统)。

关键:队列绑定交换机

// 用@Bean声明Fanout交换机+2个队列+绑定关系
@Bean
public FanoutExchange fanoutExchange() {
    return new FanoutExchange("test-fanout-exchange");
}
@Bean
public Queue fanoutQueue1() { return new Queue("fanout-queue1"); }
@Bean
public Queue fanoutQueue2() { return new Queue("fanout-queue2"); }
// 绑定队列1到交换机
@Bean
public Binding bindingFanout1(FanoutExchange fanoutExchange, Queue fanoutQueue1) {
    return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
}
// 绑定队列2到交换机
@Bean
public Binding bindingFanout2(FanoutExchange fanoutExchange, Queue fanoutQueue2) {
    return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
}

3. Routing 模式 =“按地址分区送快递,精准匹配”

类比场景

image.png

快递公司送件时,“北京朝阳区” 的快递只送朝阳网点,“上海浦东” 的只送浦东网点 ——消息带 “路由键(Routing Key)”,只有队列的绑定键和它完全匹配,才能收到消息

原理拆解

  • 用 “Direct 交换机”(像快递分拣系统,按地址关键词分拣);
  • 队列绑定交换机时,要指定 “绑定键(Binding Key)”(比如 “order.pay”);
  • 生产者发消息时,要指定 “路由键(Routing Key)”(比如 “order.pay”);
  • 只有路由键 = 绑定键,消息才会进入对应队列;
  • 特点:精准匹配,适合 “按类型分发消息”(比如订单系统,支付成功发 “order.pay”,退款成功发 “order.refund”,不同队列处理)。

4. Topics 模式 =“按关键词模糊匹配,更灵活”

类比场景

image.png

快递公司送 “生鲜食品”,不管是 “北京朝阳生鲜” 还是 “上海浦东生鲜”,都统一送 “生鲜专属网点”——用通配符模糊匹配路由键,比 Routing 模式更灵活

原理拆解

  • 用 “Topic 交换机”(支持通配符的分拣系统);
  • 绑定键支持两个通配符:
    • :匹配 1 个单词(比如 “order.” 能匹配 “order.pay”“order.refund”,但不能匹配 “order.pay.success”);
    • #:匹配 0 个或多个单词(比如 “order.#” 能匹配 “order.pay”“order.pay.success”);
  • 生产者发消息带路由键,交换机按通配符匹配绑定键,把消息分发到对应队列;
  • 特点:灵活适配多种场景,适合 “复杂分类”(比如日志系统,“log.error”“log.warn”“log.info”,用 “log.#” 绑定所有日志队列)。

5. RPC 模式 =“寄重要文件,要收件人签收回执”

类比场景

你寄一份合同,需要对方签收后给你回个 “已收到” 的短信 ——生产者发消息后,需要等待消费者处理完,返回 “响应消息”,像远程调用(RPC)一样

原理拆解

  • 流程比其他模式多一步:
  1. 生产者发 “请求消息” 到队列,同时创建一个 “临时响应队列”,等待回复;
  1. 消费者从队列拿 “请求消息”,处理完后,把 “响应消息” 发回生产者的临时队列;
  1. 生产者从临时队列拿到响应,完成一次 “调用 - 响应”;
  • 特点:需要同步等结果,适合 “需要返回值的场景”(比如远程查询用户信息,需要拿到用户数据再继续处理);
  • 踩坑提醒:别滥用!RabbitMQ 主打异步,RPC 模式会增加复杂度,能不用就不用。

二、3 种声明方式:队列 & 交换机怎么建?选对不踩坑

搞懂模型后,关键是 “怎么创建交换机和队列”?3 种方式各有适用场景,咱逐个说:

方式 1:控制台手动创建 ——“偶尔跑腿,不常用”

操作步骤

  1. 登录 RabbitMQ 控制台(http://localhost:15672 );
  1. 建交换机:点 “Exchanges”→填名字 + 选类型(Fanout/Direct/Topic)→“Add exchange”;
  1. 建队列:点 “Queues”→填名字→“Add queue”;
  1. 绑定:在交换机详情页,填队列名 + 绑定键→“Bind”。

优缺点

  • 优点:不用改代码,临时测试方便;
  • 缺点:每次环境部署都要手动建,容易漏建 / 建错,生产环境绝对不用!

方式 2:@Bean 声明 ——“提前备好,服务启动自动建”

核心逻辑

在 Spring 配置类里,用@Bean声明交换机、队列、绑定关系,项目启动时,SpringAMQP 会自动在 RabbitMQ 里创建这些资源(如果不存在)。

代码示例(Topic 模式)

@Configuration
public class RabbitTopicConfig {
    // 1. 声明Topic交换机
    @Bean
    public TopicExchange topicExchange() {
        // 交换机名、是否持久化(重启不丢)、是否自动删除
        return new TopicExchange("test-topic-exchange", true, false);
    }
    // 2. 声明队列
    @Bean
    public Queue topicQueue1() {
        return QueueBuilder.durable("topic-queue1").build(); // 持久化队列
    }
    // 3. 绑定队列到交换机(绑定键:order.#)
    @Bean
    public Binding bindingTopic1(TopicExchange topicExchange, Queue topicQueue1) {
        return BindingBuilder.bind(topicQueue1).to(topicExchange).with("order.#");
    }
}

适用场景

  • 固定的绑定关系(比如系统核心的交换机和队列);
  • 适合在配置类里统一管理,服务启动就就绪,稳定可靠。

方式 3:@RabbitListener 声明 ——“消费者自己搞定,复杂绑定也不怕”

核心逻辑

不用单独写配置类,直接在消费者方法上用@RabbitListener,注解里直接声明交换机、队列、绑定关系,项目启动时自动创建。

代码示例(广播模式)

// 消费者方法上直接声明Fanout交换机+队列+绑定
@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "listener-fanout-queue", durable = "true"), // 队列(持久化)
    exchange = @Exchange(name = "listener-fanout-exchange", type = ExchangeTypes.FANOUT), // 交换机(Fanout类型)
    key = "" // Fanout模式不用绑定键,填空
))
public void receiveFanoutByListener(String msg) {
    System.out.println("收到@RabbitListener声明的广播消息:" + msg);
}

适用场景

  • 复杂的绑定关系(比如一个消费者需要绑定多个交换机);
  • 消费者和队列强关联的场景(比如某个服务专属的队列,跟着服务代码走,不用单独管理配置)。

总结:看完就能用的 RabbitMQ 指南

  1. 五大模型记类比:简单 = 一对一,广播 = 群发,Routing = 精准匹配,Topics = 模糊匹配,RPC = 要回执;
  1. 三种声明看场景:控制台临时用,@Bean 统一配,@RabbitListener 灵活搞;
  1. 新手先从 “简单模式 +@RabbitListener” 上手,熟悉后再玩 Topics 和 Routing。

赶紧动手试试!遇到坑或者有更有趣的类比,评论区咱唠~下次再深挖 RabbitMQ 的高级玩法(死信队列、延时队列),关注不迷路~