Java 消息中间件 - RabbitMQ 全解(保姆级 2026)

从"零"到"高可用集群 + 黑科技"一步一图一命令,所有代码基于 Spring Boot 3.2 + RabbitMQ 3.12 实测可拷走。

阶段 0:学前 3 问------RabbitMQ 能干嘛?

场景 一句话
异步解耦 订单创建后 50 ms 内返回用户,后续库存、积分、短信全走消息
削峰填谷 秒杀 5w QPS 先落队列,后端按 1k QPS 消费,DB 不炸
可靠传输 生产者、队列、消费者三重确认,金融级不丢消息

阶段 1:安装------Win/Mac/Linux 3 行命令

1.装 Erlang(RabbitMQ 用它写)

bash 复制代码
# Mac (Homebrew) 
brew install erlang 
# Ubuntu 
sudo apt install erlang-base erlang-dev

2.装 RabbitMQ

bash 复制代码
# Mac 
brew install rabbitmq 
# Ubuntu 
sudo apt install rabbitmq-server

3.启管理插件(Web UI 15672)

bash 复制代码
rabbitmq-plugins enable rabbitmq_management 
sudo systemctl start rabbitmq-server

浏览器访问 http://localhost:15672 默认 guest/guest 登录成功即 OK 。

阶段 2:最简配置------Spring Boot 3 一 yml 搞定

XML 复制代码
spring: 
  rabbitmq: 
    host: localhost 
    port: 5672 
    username: guest 
    password: guest 
    virtual-host: / # 默认 
    vhost publisher-confirm-type: correlated # 生产确认 
    publisher-returns: true # 失败返回 
    listener: 
      simple: 
        acknowledge-mode: manual # 手动 
        ack concurrency: 5 # 并发 5 
        max-concurrency: 10

依赖:

XML 复制代码
<dependency> 
  <groupId>org.springframework.boot</groupId> 
  <artifactId>spring-boot-starter-amqp</artifactId> 
</dependency>

阶段 3:核心模型------一张图记住 6 大概念

XML 复制代码
Producer → Exchange → RoutingKey → Queue → Consumer
                          ↑ 
                      BindingKey
  • Exchange 类型 = 路由算法:direct(精准)| topic(模式)| fanout(广播)| headers(少用)

  • Queue 才是真正存消息的容器;Exchange 只负责转发

  • Channel 是 TCP 内的轻量连接,线程安全,推荐一条线程一个 Channel

阶段 4:Hello World------生产&消费 10 行代码

配置类(自动声明队列):

java 复制代码
@Configuration 
public class SimpleConfig { 
  @Bean 
  public Queue helloQueue() { 
    return QueueBuilder.durable("hello.q").build(); 
  } 
}

生产者:

java 复制代码
@RestController 
class Producer { 
  @Autowired private RabbitTemplate template; 

  @GetMapping("/send") 
  public String send(@RequestParam String msg) { 
     template.convertAndSend("hello.q", msg); 
     return "ok"; 
  } 
}

消费者:

java 复制代码
@Component 
public class HelloConsumer { 
  @RabbitListener(queues = "hello.q") 
  public void receive(String msg, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException { 
    System.out.println("收到 = " + msg); 
    channel.basicAck(tag, false); // 手动 ack 
  } 
}

启动后访问 http://localhost:8080/send?msg=abc 控制台打印即成功 。

阶段 5:4 种交换机------口诀一张表

类型 路由规则 关键词 场景
direct 完全匹配 RoutingKey info.log → info.log 单播、任务分发
topic 模式匹配 * 单层 # 多层 order.* 分类订阅
fanout 无视 key,广播全部队列 公告、配置下发
headers 头部 KV 匹配 x-match=any 少用大流量

代码示例(topic 模式):

java 复制代码
@Bean 
public TopicExchange topicEx() { 
  return ExchangeBuilder.topicExchange("topic.ex").durable(true).build(); 
} 
@Bean 
public Binding topicBinding() { 
  return BindingBuilder
              .bind(QueueBuilder.durable("topic.q").build()) 
              .to(topicEx())
              .with("order.*"); 
}

阶段 6:消息可靠性------3 确认 2 补偿

1.生产者确认(callback)

java 复制代码
template.setConfirmCallback((correlation, ack, cause) -> { 
  if (ack) log.info("消息已送达交换机"); 
  else log.error("消息未送达,cause={}", cause); 
});

2.mandatory=true + 返回回调 → 交换机→队列失败时触发

java 复制代码
template.setReturnsCallback(returned -> log.error("队列投递失败,消息={}", 
returned.getMessage()));

3.消费者手动 ack / nack / reject

java 复制代码
channel.basicAck(tag, false); // 成功 
channel.basicNack(tag, false, true); // 失败重入队 
channel.basicReject(tag, false); // 抛弃/死信

面试口诀:"投递确认 + 失败返回 + 消费ack" 3 连击,RabbitMQ 不丢消息 。

阶段 7:死信队列(DLX)------失败消息归宿

死信触发条件:拒绝且 requeue=false / 超时 / 队列满 配置:

java 复制代码
@Bean 
public Queue bizQueue() { 
  return QueueBuilder.durable("biz.q") 
                     .deadLetterExchange("dlx.ex") 
                     .deadLetterRoutingKey("dlx") .ttl(5000) // 5 秒超时 
                     .build(); 
} 

@Bean 
public Queue dlxQueue() { 
  return QueueBuilder.durable("dlx.q").build(); 
} 

@Bean 
public DirectExchange dlxEx() { 
  return ExchangeBuilder.directExchange("dlx.ex").build(); 
} 

@Bean 
public Binding dlxBind() { 
  return BindingBuilder.bind(dlxQueue()).to(dlxEx()).with("dlx"); 
}

消费 dlx.q 即可统一处理超时/失败订单,做补偿或告警。

阶段 8:延迟消息------2 种实现

  1. TTL + DLX(无插件,精度秒级) 见阶段 7 代码,队列级 TTL 或消息级 TTL均可。

  2. 插件 rabbitmq_delayed_message_exchange(毫秒级)

安装:

bash 复制代码
rabbitmq-plugins enable rabbitmq_delayed_message_exchangeJava

代码:

java 复制代码
@Bean 
public CustomExchange delayEx() { 
  return ExchangeBuilder 
            .customExchange("delay.ex", "x-delayed-message") 
            .args(Map.of("x-delayed-type", "direct")) 
            .build(); 
}

发送时加头:

java 复制代码
template.convertAndSend("delay.ex", "delay.key", msg, m -> { 
   m.getMessageProperties().setDelay(3000); // 3 秒 
   return m; 
});

阶段 9:批量与异步------高吞吐玩法

异步发送(不阻塞主线程):

java 复制代码
template.setUsePublisherConnection(true); // 独立连接 
CompletableFuture<Void> future = template.asyncSend("batch.q", msg);

批量发送(减少 RTT):

java 复制代码
List<Message> batch = msgs.stream() 
    .map(m ->MessageBuilder.withBody(m.getBytes()).build()) 
    .collect(Collectors.toList()); 

template.invoke(t -> { 
   batch.forEach(b -> t.convertAndSend("batch.q", b)); 
   return null; 
}, null);

阶段10:监控 & 指标------一眼看出瓶颈

1.管理 UI http://host:15672 → Queues 标签看 Message rates / Deliver / Ack

2.Prometheus + Grafana 启用插件:

bash 复制代码
rabbitmq-plugins enable rabbitmq_prometheus

端口 15692 暴露指标,Grafana 模板 RabbitMQ-Overview 直接导入,Delivery rate、Memory、Disk space 三红线预警。

3.消费者 Lag = Ready 消息数,持续 > 1w 即要扩容或加线程。

阶段11:集群 & 高可用------3 节点最小

普通集群(队列仍单点):

bash 复制代码
# node2 加入 node1 
rabbitmqctl stop_app 
rabbitmqctl join_cluster 
rabbit@node1 rabbitmqctl start_app

镜像队列(高可用):

bash 复制代码
rabbitmqctl set_policy ha "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

镜像数量 = 2 即可,=节点数 会全网复制,IO 爆炸 。

故障切换: 节点宕机 → 镜像队列自动提升为 master,业务无感知;原节点恢复 → 自动同步后再次加入集群。

阶段12:黑科技 & 踩坑大全

黑科技

  1. 流式插件 rabbitmq-stream(Kafka 风格) 百万级 QPS、分段日志,一条连接可并发读,适合日志/埋点。

  2. Federation = 跨机房消息复制,异地多活利器。

  3. Shovel = 动态迁移队列,0 停机搬迁数据。

  4. MQTT 插件 → 物联网设备直接 PUBLISH 到 RabbitMQ。

  5. 内部 tracing → 启用 rabbitmq_tracing,消息路径全链路落盘,排障神器。

踩坑 & 急救

现象 急救
连接泄漏 connection_count 飙高 一定 channel.close();Spring 默认缓存,别自己 new
消息堆积 Ready 数暴涨 加消费者线程 or 扩容队列;禁止 autoAck=true
磁盘写满 阻塞所有 publish 设 disk_free_limit.absolute=2GB;日志/镜像及时清理
镜像过多 性能暴跌 镜像数 ≤ 2,≠ 节点数
TTL 无效 延迟不生效 必须队列级或消息级二选一,同时存在以最小值为准

总结口诀(背诵 30 秒)

"Exchange 管路由,Queue 才存货; 3 确认 2 死信,集群镜像别过多; TTL+DLX 做延迟,Stream 插件破百万; 连接要关,镜像要清,Prometheus 看 Lag!"

收藏这篇,从单机到异地多活,RabbitMQ 任你摆布!

相关推荐
Qiuner17 小时前
Spring Boot 全局异常处理策略设计(三):@ExceptionHandler 与 @ControllerAdvice 生效原理源码解析
java·spring boot·后端
u01040583617 小时前
企业微信自建应用权限模型与 RBAC 在 Spring Security 中的映射
java·spring·企业微信
墨雨晨曦8817 小时前
通过调用deepseek的api来实现智能客服
java
予枫的编程笔记17 小时前
Elasticsearch核心架构与基础原理:解密其极速性能的底层逻辑
java·大数据·人工智能·elasticsearch·搜索引擎·架构·全文检索
Seven9717 小时前
数据结构-图
java
Yu_iChan17 小时前
苍穹外卖Day09 地址簿模块
java·数据库·mybatis
Java天梯之路17 小时前
Spring Boot 钩子全集实战(五):ApplicationContextInitializer详解
java·spring boot·后端
后端小张18 小时前
【AI 学习】AI提示词工程:从入门到实战的全栈指南
java·人工智能·深度学习·学习·语言模型·prompt·知识图谱