简介
- Producer: 发送消息的应用程序或服务。生产者将消息发送到交换机。
- Exchange: 负责接收来自生产者的消息,并根据路由规则将其转发到一个或多个队列。RabbitMQ 支持几种类型的交换机:
- Direct Exchange: 精确匹配路由键的队列。
- Fanout Exchange: 将消息广播到所有绑定的队列。
- Topic Exchange: 基于主题模式(通配符)进行路由。
- Headers Exchange: 使用消息头进行路由。
- Queue: 存储消息的地方。队列中的消息按照先进先出(FIFO)顺序处理。
- Consumer: 从队列中接收和处理消息的应用程序或服务。消费者可以从一个或多个队列中获取消息。
- Binding(绑定): 定义交换机和队列之间的关系。通过绑定,交换机知道如何将消息路由到队列。
- Virtual Hosts(虚拟主机): 提供了逻辑上的隔离,可以在同一个 RabbitMQ 实例中创建多个独立的环境。
- Management Plugin(管理插件): 提供 Web 界面和 API,用于管理和监控 RabbitMQ 的状态和性能。
工作原理
- 生产者将消息发送到交换机,指定一个路由键。
- 交换机根据路由键和绑定关系决定将消息转发到哪个队列。不同类型的交换机(如直连、主题、扇出)有不同的路由策略。
- 被转发的消息存储在一个或多个队列中,等待消费者处理。
- 消费者从队列中获取消息,进行处理。可以选择手动或自动确认消息。
- 消费者处理完消息后,发送确认给 RabbitMQ,以便删除该消息。如果处理失败,可以选择不确认,RabbitMQ 将重新投递消息。
- 通过这一流程,RabbitMQ 实现了异步通信和负载均衡,提高了系统的可靠性和扩展性。
Direct Exchange
RabbitMQ 中的 Direct Exchange 是一种消息路由机制,它根据路由键将消息精确地路由到一个或多个绑定的队列。
- 路由键: 每个发送到 Direct Exchange 的消息都带有一个路由键。交换机会根据这个路由键找到与之匹配的队列。
- 精确匹配: 只有那些绑定到交换机并且路由键与消息中的路由键完全匹配的队列才会接收到消息。
- 多个队列: 一个 Direct Exchange 可以绑定多个队列,这样相同的消息可以发送到多个队列,只要它们的路由键匹配。
使用场景
- 点对点通信: 适合需要将消息发送到特定队列的场景,比如任务处理系统。
- 简单的消息分发: 可以将消息发送到多个消费者,通过不同的路由键进行区分。
Fanout Exchange
RabbitMQ 中的 Fanout Exchange 是一种将消息广播到所有绑定交换机的队列。
- 广播功能: 发送到 Fanout Exchange 的消息会被传递到所有绑定的队列,无需考虑路由键。
- 无路由键过滤: 不管消息的路由键是什么,所有绑定到该交换机的队列都会接收到消息。
- 适合广播场景: 特别适用于需要将同一条消息发送给多个消费者的场景。
使用场景
- 实时通知: 比如聊天应用中的消息推送。
- 日志记录: 将日志消息发送到多个日志处理系统。
- 事件发布: 将事件发布给所有感兴趣的消费者。
Topic Exchange
RabbitMQ 中的 Topic Exchange 是一种强大的消息路由机制,允许根据主题模式将消息路由到多个队列。
- 基于主题的路由: Topic Exchange 使用路由键的模式匹配来决定消息的去向。路由键可以包含多个词,使用点号(.)分隔。
- 通配符支持: Topic Exchange 支持两种通配符:
- *(星号): 匹配一个词。
- #(井号): 匹配零个或多个词。
- 灵活的路由: 允许更复杂的消息路由逻辑,适合多种场景。
使用场景
- 多层次分类: 可以根据主题对消息进行分类,例如日志消息可以按级别(如 error, info)和模块(如 auth, payment)路由。
- 事件驱动架构: 适合处理复杂的事件通知,支持不同的消费者对不同主题感兴趣。
Headers Exchange
RabbitMQ 中的 Headers Exchange 是一种基于消息头部属性进行路由的交换机类型。
- 基于头部的路由: 消息被发送到 Headers Exchange 时,路由决策基于消息的头部属性,而不是路由键。
- 匹配条件: 可以定义多个头部属性的匹配条件,支持使用 x-match 参数:
- all: 所有头部属性都必须匹配。
- any: 只需任意一个头部属性匹配。
- 灵活性: 允许更复杂的路由逻辑,适用于多种场景。
使用场景
- 复杂路由需求: 当需要基于多个属性来决定消息路由时,使用 Headers Exchange 可以提供更高的灵活性。
- 多样化消息分类: 适合处理多维度的消息分类,例如根据多个消息属性进行路由。
死信队列
RabbitMQ 中的死信队列(Dead Letter Queue, DLQ)用于处理无法被正常消费的消息。当消息因为某些原因无法被处理时(如超时、消费失败、队列达到最大长度等),这些消息可以被发送到一个指定的死信队列,以便后续的分析和处理。
死信条件
- 消息被拒绝(basic.reject 或 basic.nack)并且没有重新排入队列。
- 超出最大重试次数:当消息在被消费的过程中多次重试仍然失败时,如果设置了最大重试次数,超过后将被送入死信队列。
- 消息 TTL(存活时间)到期。
- 队列达到最大长度。
配置死信队列
- 创建一个专门的队列来接收死信。
- 在原始队列中设置 x-dead-letter-exchange 和 x-dead-letter-routing-key 属性,指定死信交换机和路由键。
@Configuration
public class RabbitConfig {
public static final String MAIN_QUEUE = "mainQueue";
public static final String DLQ_QUEUE = "deadLetterQueue";
public static final String DLX_EXCHANGE = "deadLetterExchange";
public static final String DLQ_ROUTING_KEY = "deadLetterRoutingKey";
@Bean
public Queue mainQueue() {
// 设置死信交换机和路由键
Map<String, Object> args = new HashMap<>();
args.put("x-dead-letter-exchange", DLX_EXCHANGE); // 指定死信交换机
args.put("x-dead-letter-routing-key",