RabbitMQ 交换机不神秘!类比快递分拣中心,5 分钟搞懂消息路由规则

基本概念

RabbitMQ 组件快递系统类比核心作用
生产者(Producer)寄件人生成消息(快递)并发送给交换机(分拣中心)。
交换机(Exchange)快递分拣中心根据规则(路由键)将消息(快递)分配到不同的队列(快递柜 / 快递点)。
队列(Queue)快递柜 / 快递点存储消息(快递),供消费者(收件人)读取。
消费者(Consumer)收件人从队列(快递柜)中获取消息(快递)并处理。
路由键(Routing Key)快递面单上的地址 / 电话交换机(分拣中心)根据路由键(地址)判断消息(快递)该流向哪个队列(快递点)。
绑定(Binding)分拣中心到快递柜的配送路线定义交换机(分拣中心)与队列(快递柜)的关联关系(如 “朝阳区包裹送到 A 快递柜”)。
信道(Channel)快递员的配送路线(虚拟管道)在连接(物流公司)上创建的轻量级虚拟连接,用于高效传输消息(快递)。
连接(Connection)物流公司的运输网络生产者 / 消费者(寄件人 / 收件人)与 Broker(快递总站)之间的物理网络连接。
Broker超级快递总站管理所有交换机、队列和连接的 RabbitMQ 服务实例,提供消息传递的基础设施。

交换机:类似快递智能分拣中心

交换机就像一个「智能快递分拣中心」,它从寄件人(生产者)接收包裹(消息)后,根据快递单上的地址(路由键)和预设的分拣规则(交换机类型),决定:

  1. 转发到指定快递柜(绑定队列):例如标注「朝阳区」的包裹会被分到朝阳区的快递柜;

  2. 直接退回 / 销毁(消息丢弃):如果地址错误或无人签收,包裹可能被退回或销毁;

  3. 设置保留时间(消息过期):如生鲜快递(时效性消息)会标注「24 小时内送达」,超时未取则退回

Broker:类似超级快递总站

Broker = 整个快递总站,它包含:

  1. 多个分拣中心(交换机):处理不同类型的包裹(消息);

  2. 大量快递柜(队列):暂存包裹直到被取走;

  3. 传送带和分拣设备(网络和协议):负责包裹的传输和处理。

信道:

  • 类比:同一家物流公司的多个快递员可以共享一条运输路线(连接),每个快递员负责不同区域的配送(信道),提高效率。

  • 技术解释:信道是连接中的虚拟连接,允许多个线程或进程通过同一个 TCP 连接高效地传输消息

绑定(Binding)

  1. 类比:快递公司规定「所有发往朝阳区的包裹都送到 A 快递柜」,这里的「朝阳区 → A 快递柜」就是一个绑定。

  2. 技术解释:绑定是交换机和队列之间的关联,通过路由键或其他条件定义消息的流向。

交换机类型的具体类比

交换机类型快递分拣规则场景示例
Direct按精确地址分拣(如 “朝阳区建国路 88 号”)订单系统中,按订单状态(status=paid)将消息路由到对应队列。
Topic按地址关键词分拣(支持通配符)物联网系统中,按 设备类型.区域 路由消息(如 device.car.beijing)。
Headers按包裹属性分拣(如重量、尺寸)物流系统中,按包裹重量(weight>5kg)路由到不同处理队列。
Fanout广播到所有快递柜系统通知模块,将公告同时发送到所有用户的收件箱。

完整的过程:

1. 用户触发订单(生产者发送消息)
  • 快递流程:用户在电商平台下单,填写收货地址、联系方式等信息,包裹被打包并贴上快递单。

  • RabbitMQ:生产者(Producer)创建一条消息,包含:

    • 消息体(Body):实际数据(如订单信息)。

    • 路由键(Routing Key):类似快递单上的“地址”(如 order.payment)。

    • 属性(Properties):类似快递单的附加信息(如优先级、过期时间)。

  • 技术细节:

    • 生产者通过 AMQP 协议将消息发送到 Broker 的指定交换机(Exchange)。

    • 消息可能设置 TTL(Time-To-Live),类似生鲜包裹的“24小时内送达”标签。

2. 消息到达 Broker(快递总站)
  • 快递流程:包裹被运输到快递公司的中央分拣中心(总站),准备分拣。

  • RabbitMQ:

    • Broker 是 RabbitMQ 服务实例,包含交换机、队列、虚拟主机等组件。

    • 消息首先到达指定的交换机(类似分拣中心入口)。

  • 技术细节:

    • Broker 可能部署为集群(类似多个分拣中心协同工作)。

    • 消息会经过虚拟主机(Virtual Host)隔离,类似快递总站的不同分区(如“国内件区”和“国际件区”)。

在这里插入图片描述
在这里插入图片描述

3. 交换机路由消息(分拣中心处理)
  • 快递流程:分拣中心根据快递单地址和分拣规则,将包裹分到对应区域的传送带。

  • RabbitMQ:交换机根据类型和绑定规则决定消息去向:

    • 交换机类型:

      • Direct(直连):精确匹配路由键,类似“仅配送朝阳区望京路1号”。

      • Fanout(广播):无视路由键,发到所有绑定队列,类似“小区广播通知”。

      • Topic(主题):模糊匹配路由键(如 order.*),类似“配送所有以‘order’开头的地址”。

      • Headers(头部匹配):忽略路由键,通过消息头属性匹配,类似“根据包裹特殊标签分拣”。

    • 绑定(Binding):交换机与队列的关联规则(如路由键 order.payment 绑定到 payment_queue)。

  • 技术细节:

    • 若消息无匹配队列,可能被丢弃(需设置 mandatory 标志决定是否返回生产者)。

    • 可设置备用交换机(Alternate Exchange)处理无法路由的消息,类似“地址错误的包裹转到异常处理中心”。

4. 消息存入队列(包裹进入快递柜)
  • 快递流程:分拣后的包裹被暂存到对应区域的快递柜,等待配送员取件。

  • RabbitMQ:

    • 队列(Queue)是消息的缓冲区,消费者从中获取消息。

    • 队列属性:

      • 持久化(Durable):快递柜断电不丢件(重启后消息保留)。

      • 独占(Exclusive):仅允许一个消费者使用,类似“VIP专属快递柜”。

      • 自动删除(Auto-delete):无消费者时自动销毁,类似“临时寄存柜”。

  • 技术细节:

    • 队列可设置长度限制(x-max-length),类似快递柜满时拒收新包裹。

    • 消息在队列中遵循 FIFO(默认)或优先级规则。

5. 消费者处理消息(快递员配送)
  • 快递流程:快递员从快递柜取件,配送到用户手中,用户签收后流程结束。

  • RabbitMQ:

    • 消费者(Consumer)从队列拉取(Pull)或订阅(Push)消息。

    • 处理方式:

      • 手动应答(ACK):消费者处理成功后显式确认,类似“用户签收后快递员反馈系统”。

      • 自动应答(Auto-ACK):消息被取出即视为成功,风险类似“包裹放门口即算送达”。

      • 拒绝(Reject/NACK):处理失败时可重新入队或丢弃,类似“用户拒收后退回或销毁”。

  • 技术细节:

    • 消费者可设置 QoS(预取计数),限制未确认消息数,类似“快递员一次最多拿5个包裹”。

    • 消息可能因超时(TTL)或死信队列(DLX)机制转入异常处理。

Springboot整合rabbitmq

1. 添加 RabbitMQ 依赖

pom.xml 中引入 Spring Boot AMQP starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
  • 该依赖包含了 RabbitMQ Java 客户端(com.rabbitmq:amqp-client)和 Spring 对 AMQP 的封装工具。
2. 配置 RabbitMQ 连接信息

在 application.yml 或 application.properties 中配置服务器地址、认证信息等:

spring:
  rabbitmq:
    addresses: localhost:5672       # RabbitMQ 服务器地址(支持多地址,用逗号分隔)
    username: guest                # 用户名(默认 guest)
    password: guest                # 密码(默认 guest)
    virtual-host: /                 # 虚拟主机(默认 /)
    # 可选配置:
    # listener.simple.concurrency: 10  # 监听容器的并发数
    # publisher-confirm-type: correlated  # 开启发布确认机制
  • 配置项说明:

  • addresses:RabbitMQ 服务的 IP 和端口(默认端口 5672)。

  • virtual-host:相当于逻辑隔离的 “数据库”,不同虚拟主机中的队列、交换机相互隔离。

  • username/password:访问 RabbitMQ 的账号密码(需与服务器配置一致)。

3. Spring 自动创建连接工厂(ConnectionFactory)
  • 核心类:Spring Boot 会自动创建 CachingConnectionFactory(ConnectionFactory 的子类),用于管理与 RabbitMQ 服务器的物理连接。

  • CachingConnectionFactory 支持连接池和通道缓存,避免频繁创建连接 / 通道带来的性能开销。

  • 自动配置逻辑:

  • Spring 通过 RabbitAutoConfiguration 类读取 spring.rabbitmq 配置,初始 化 CachingConnectionFactory。

  • 若未自定义 ConnectionFactory,则使用默认配置;若自定义,则覆盖默认 Bean。

4.Spring Boot AMQP(自动连接)

通过依赖注入直接使用 AmqpTemplateRabbitTemplate

springboot直接扫描 application.yml中的配置文件进行注入,直接读取

@Resource
private AmqpTemplate amqpTemplate;  // 由 Spring 自动配置并注入

public void sendMessage(long orderId, long delayTimes) {
    // 直接使用注入的模板发送消息,无需手动管理连接
    amqpTemplate.convertAndSend(...);
}
// 原生 RabbitMQ 客户端连接方式
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setUsername("guest");
factory.setPassword("guest");
try (Connection connection = factory.newConnection();
     Channel channel = connection.createChannel()) {
    // 声明队列、发送消息等操作
}

此配置不需要了

5. 声明队列、交换机和绑定(自动或手动)

Spring Boot 提供两种方式声明 RabbitMQ 组件:

方式一:自动声明(推荐)

通过 @Bean 在配置类中手动声明队列、交换机和绑定关系(如代码中的 RabbitConfig):

@Configuration
public class RabbitConfig {
    // 声明交换机
    @Bean
    public DirectExchange orderCancelDirectExchange() {
        return new DirectExchange("order-cancel-exchange", true, false); // 持久化交换机
    }

    // 声明队列(绑定死信队列)
    @Bean
    public Queue orderCancelQueue() {
        return QueueBuilder.durable("order-cancel-queue") // 持久化队列
                .deadLetterExchange("order-cancel-ttl-exchange") // 设置死信交换机
                .deadLetterRoutingKey("order-cancel-ttl-route-key") // 设置死信路由键
                .build();
    }

    // 声明绑定关系
    @Bean
    public Binding orderCancelBinding() {
        return BindingBuilder.bind(orderCancelQueue())
                .to(orderCancelDirectExchange())
                .with("order-cancel-route-key"); // 路由键匹配
    }
}
1. Binding 的概念
  • 定义:Binding 是 RabbitMQ 中交换机 (Exchange) 与队列 (Queue) 之间的关联关系

  • 作用:决定消息如何从交换机路由到队列

  • 类比:类似于数据库中的外键约束,定义表与表之间的关系

2. 代码解析

2.1 BindingBuilder.bind(orderCancelQueue())

  • 功能:指定要绑定的目标队列

  • 参数:

  • orderCancelQueue():通过方法引用获取队列 Bean

  • 对应配置中的队列名称:order-cancel-queue

  • 注意:

  • 队列必须先通过@Bean声明

  • 绑定的队列必须与交换机类型兼容

2.2 .to(orderCancelDirectExchange())

  • 功能:指定绑定的目标交换机

  • 参数:

  • orderCancelDirectExchange():通过方法引用获取交换机 Bean

  • 对应配置中的交换机名称:order-cancel-exchange

  • 注意:

  • 交换机必须先通过@Bean声明

  • 不同类型交换机的绑定规则不同

2.3 .with(“order-cancel-route-key”)

  • 功能:指定绑定的路由键 (Routing Key)

  • 路由键作用:

  • 对于 DirectExchange:消息根据路由键精确匹配

  • 对于 TopicExchange:支持通配符匹配

  • 对于 FanoutExchange:忽略路由键,直接广播到所有绑定队列

  • 匹配规则:

  • 当消息的路由键等于order-cancel-route-key时

  • 消息会从order-cancel-exchange交换机路由到order-cancel-queue队列

  • 关键注解:

  • @Bean:告诉 Spring 容器创建并管理这些组件。

  • QueueBuilder.durable():设置队列持久化,避免 RabbitMQ 重启后数据丢失。

方式二:自动创建(基于注解)

若在配置中开启 spring.rabbitmq.listener.simple.auto-startup=true(默认 true),Spring 会根据监听注解(如 @RabbitListener)自动创建队列。

6. 发送与接收消息

通过 AmqpTemplate 的 convertAndSend 方法发送消息,自动使用配置好的连接工厂:

public void sendMessage(long orderId, long delayTimes) {
    amqpTemplate.convertAndSend(
        "order-cancel-exchange",       // 交换机名称
        "order-cancel-route-key",      // 路由键
        orderId,                       // 消息内容(可序列化对象)
        message -> {
            message.getMessageProperties().setExpiration(String.valueOf(delayTimes)); // 设置消息 TTL
            return message;
        }
    );
}

接收消息通过 @RabbitListener 注解监听队列,Spring 自动从连接工厂获取通道并消费消息

@RabbitListener(queues = "order-cancel-ttl-queue") // 监听死信队列
public class CancelOrderReceiver {
    @RabbitHandler // 处理消息的方法(可省略,默认用参数为消息体的方法)
    public void handle(Long orderId) {
        // 处理订单取消逻辑
    }
}

核心组件与自动配置类

1. 关键 Bean
Bean 名称类型作用描述
connectionFactoryCachingConnectionFactory管理与 RabbitMQ 的物理连接,支持连接池
rabbitTemplateRabbitTemplate发送 / 接收消息的核心模板类
rabbitAdminRabbitAdmin管理队列、交换机的声明与绑定
simpleRabbitListenerContainerFactorySimpleRabbitListenerContainerFactory监听容器工厂,创建消息监听容器
2. 自动配置类
  • RabbitAutoConfiguration:核心自动配置类,负责创建 ConnectionFactory、RabbitTemplate 等 Bean。

  • RabbitListenerAnnotationBeanPostProcessor:处理 @RabbitListener 注解,自动创建监听容器。

接收消息

通过 @RabbitListener 注解监听队列,Spring 自动从连接工厂获取通道并消费消息:

@RabbitListener(queues = "order-cancel-ttl-queue") // 监听死信队列
public class CancelOrderReceiver {
    @RabbitHandler // 处理消息的方法(可省略,默认用参数为消息体的方法)
    public void handle(Long orderId) {
        // 处理订单取消逻辑
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值