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 任你摆布!

相关推荐
徐徐同学12 小时前
cpolar为IT-Tools 解锁公网访问,远程开发再也不卡壳
java·开发语言·分布式
Mr.朱鹏13 小时前
Nginx路由转发案例实战
java·运维·spring boot·nginx·spring·intellij-idea·jetty
白露与泡影14 小时前
2026版Java架构师面试题及答案整理汇总
java·开发语言
历程里程碑14 小时前
滑动窗口---- 无重复字符的最长子串
java·数据结构·c++·python·算法·leetcode·django
qq_2290580115 小时前
docker中检测进程的内存使用量
java·docker·容器
我真的是大笨蛋15 小时前
InnoDB行级锁解析
java·数据库·sql·mysql·性能优化·数据库开发
钦拆大仁15 小时前
Java设计模式-单例模式
java·单例模式·设计模式
小手cool15 小时前
在保持数组中对应元素(包括负数和正数)各自组内顺序不变的情况下,交换数组中对应的负数和正数元素
java
笨手笨脚の15 小时前
深入理解 Java 虚拟机-04 垃圾收集器
java·jvm·垃圾收集器·垃圾回收
skywalker_1115 小时前
Java中异常
java·开发语言·异常