🐇 RabbitMQ 核心概念速查表
| 核心概念 | 作用 | 关键特性 / 注意事项 |
|---|---|---|
| Producer | 消息发送方 | 只与 Exchange 交互,对 Queue 无感知 |
| Consumer | 消息接收/处理方 | 只订阅 Queue,支持多消费者竞争消费(负载均衡) |
| Exchange | 消息路由器 | 不存储消息;按类型(Direct/Topic/Fanout/Headers)和 Binding 规则转发 |
| Queue | 消息缓冲区 | 真正存储消息的地方;FIFO 原则;可绑定多个 Exchange |
| Binding | 路由规则 | 连接 Exchange 与 Queue 的桥梁;可携带 Routing Key 或 Headers |
| Routing Key | 路由关键字 | 生产者发送时指定,Exchange 用它与 Binding Key 做匹配 |
| VHost | 虚拟主机 | 逻辑隔离单元(类似 MySQL 的 Database);独立权限、Exchange、Queue 体系 |
| Connection | 物理 TCP 连接 | 开销大,应用中应复用 |
| Channel | 逻辑通道 | 共享同一个 Connection 的轻量级通信管道;线程不安全,每线程独立 Channel |
💡 消息流转一句话总结
Producer → (Routing Key) → Exchange → (Binding 匹配) → Queue → Consumer
☕ Spring Boot 中最简使用方式
pring AMQP 封装了原生 SDK,通过注解即可完成 90% 的场景。
1. 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2. 配置文件 application.yml
java
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
# 发送端防丢:路由失败时退回消息而非静默丢弃
template:
mandatory: true
# 开启手动确认(生产环境建议开启)
listener:
simple:
acknowledge-mode: manual
3. 声明交换机、队列、绑定关系
@Configuration
public class RabbitConfig {
public static final String TOPIC_EXCHANGE = "order.exchange";
public static final String ORDER_QUEUE = "order.queue";
public static final String ROUTING_KEY = "order.created.*";
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(TOPIC_EXCHANGE);
}
@Bean
public Queue orderQueue() {
// durable=true: 持久化,RabbitMQ 重启后队列仍在
return QueueBuilder.durable(ORDER_QUEUE).build();
}
@Bean
public Binding binding(Queue orderQueue, TopicExchange topicExchange) {
return BindingBuilder.bind(orderQueue)
.to(topicExchange)
.with(ROUTING_KEY);
}
}
4. 生产者:发送消息
java
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderService {
private final RabbitTemplate rabbitTemplate;
// ✅ 注册退回回调:mandatory=true 时必须配置,否则退回的消息依然会丢失
@PostConstruct
public void initReturnsCallback() {
rabbitTemplate.setReturnsCallback(returned -> {
log.error("❌ 消息路由失败被退回! replyCode={}, routingKey={}, message={}",
returned.getReplyCode(),
returned.getRoutingKey(),
new String(returned.getMessage().getBody()));
// TODO: 写入补偿表 / 发送告警 / 记录日志
});
}
public void createOrder(String orderId) {
rabbitTemplate.convertAndSend(
RabbitConfig.TOPIC_EXCHANGE,
"order.created.vip",
orderId
);
log.info("✅ 订单消息已发送: {}", orderId);
}
}
5. 消费者:监听并处理消息
java
@Component
@Slf4j
public class OrderConsumer {
@RabbitListener(queues = RabbitConfig.ORDER_QUEUE)
public void handleOrder(
@Payload String orderId,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag
) throws IOException {
try {
log.info("📦 收到订单消息: {}", orderId);
// TODO: 业务处理逻辑
channel.basicAck(deliveryTag, false);
} catch (Exception e) {
log.error("❌ 处理失败: {}", e.getMessage());
// requeue=false → 进入死信队列,避免无限重试阻塞主队列
channel.basicNack(deliveryTag, false, false);
}
}
}
⚠️ 生产环境必知要点
| 防丢环节 | 配置 / 代码 | 防护场景 | 缺失后果 |
|---|---|---|---|
| 发送端-路由失败 | mandatory: true + ReturnsCallback |
Routing Key 未匹配到 Queue,消息是否从Exchange路由到Queue | 消息被 Broker 静默丢弃 |
| 发送端-Broker确认 | publisher-confirms-type: correlated |
消息未到达 Exchange/Queue | Broker 宕机或内部错误导致丢失 |
| 消息持久化 | Exchange/Queue durable=true + Message deliveryMode=2 |
RabbitMQ 重启 | 内存中的消息全部丢失 |
| 消费端-处理失败 | acknowledge-mode: manual + basicAck/Nack |
消费者崩溃 / 业务异常 | 消息被自动 ACK 后永久丢失 |
| 消费端-兜底 | 死信队列 (DLX) + 延迟插件 | 多次重试仍失败的消息 | 毒消息阻塞主队列或彻底丢失 |
⚠️ 高频踩坑提醒
- mandatory 单独配置无效 :必须搭配
ReturnsCallback,否则退回消息无人接收等同于丢失。 - manual ACK 忘记确认 :所有 try-catch 分支都必须有
basicAck或basicNack,否则 Unacked 堆积导致消费者停摆。 - 本地重试 ≠ 服务端重试 :
retry.max-attempts是 JVM 内同步重试,持续性故障应 NACK 进死信队列做异步延迟重试。 - 高并发必配 prefetch :
concurrency: 20不配prefetch-count会导致单次拉取 5000+ 消息,极易 OOM。