深入理解 RabbitMQ 的交换机类型(Exchange Types)
一、什么是交换机(Exchange)?
RabbitMQ 的核心工作机制可以总结为:
生产者 ➝ 交换机 ➝ 队列 ➝ 消费者
交换机负责接收消息,并根据不同类型的路由规则,将消息转发到一个或多个队列
每个交换机都有:
- 名称(可以为空)
- 类型(direct、fanout、topic、headers)
- 绑定关系(Binding)用于指定哪些队列接收哪些消息
二、交换机的四种类型
| 类型 | 名称 | 特点说明 |
|---|---|---|
| 直连型 | direct | 精准路由,依据 routingKey 完全匹配 |
| 扇出型 | fanout | 广播模式,忽略 routingKey,发送给所有队列 |
| 主题型 | topic | 模糊匹配,支持通配符(* 和 #) |
| 头部型 | headers | 根据消息头(headers)匹配路由规则 |
三、direct(直连)交换机
✨ 特点
- routingKey 精准匹配
- 每条消息只会进入绑定了指定 routingKey 的队列

🧪 示例

- 声明一个名为
hmall.direct的交换机 - 声明队列
direct.queue1,绑定hmall.direct,bindingKey为blud和red - 声明队列
direct.queue2,绑定hmall.direct,bindingKey为yellow和red - 在
consumer服务中,编写两个消费者方法,分别监听direct.queue1和direct.queue2 - 在
publisher中编写测试方法,向hmall.direct发送消息
消息接收:
@RabbitListener(queues = "direct.queue1")
public void listenDirectQueue1(String msg) {
System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}
@RabbitListener(queues = "direct.queue2")
public void listenDirectQueue2(String msg) {
System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}
消息发送
@Test
public void testSendDirectExchange() {
// 交换机名称
String exchangeName = "hmall.direct";
// 消息
String message = "红色警报!日本乱排核废水,导致海洋生物变异,惊现哥斯拉!";
// 发送消息
rabbitTemplate.convertAndSend(exchangeName, "bule", message);
}
消息将被投递到绑定了 "blue" 的队列。
四、fanout(扇出)交换机
✨ 特点
- 不关心 routingKey
- 消息被 广播到所有绑定的队列

- 1) 可以有多个队列
- 2) 每个队列都要绑定到Exchange(交换机)
- 3) 生产者发送的消息,只能发送到交换机
- 4) 交换机把消息发送给绑定过的所有队列
- 5) 订阅队列的消费者都能拿到消息
🧪 示例

- 创建一个名为
hmall.fanout的交换机,类型是Fanout - 创建两个队列
fanout.queue1和fanout.queue2,绑定到交换机hmall.fanout
消息发送:
@Test
public void testFanoutExchange() {
// 交换机名称
String exchangeName = "hmall.fanout";
// 消息
String message = "hello, everyone!";
rabbitTemplate.convertAndSend(exchangeName, "", message);
}
消息接收:
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {
System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}
@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {
System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
消息会同时发送给fanout.queue1和fanout.queue2。
✅ 应用场景
- 广播通知(如:发短信、发邮件)
- 多系统日志收集
五、topic(主题)交换机
✨ 特点
- 支持模糊匹配 routingKey(以点分隔)
- 通配符说明:
*匹配一个单词(例如order.*)#匹配多个单词(例如order.#)
🧪 示例

假如此时publisher发送的消息使用的RoutingKey共有四种:
china.news代表有中国的新闻消息;china.weather代表中国的天气消息;japan.news则代表日本新闻japan.weather代表日本的天气消息;
解释:
topic.queue1:绑定的是china.#,凡是以china.开头的routing key都会被匹配到,包括:china.newschina.weather
topic.queue2:绑定的是#.news,凡是以.news结尾的routing key都会被匹配。包括:china.newsjapan.news
消息发送:
/**
* topicExchange
*/
@Test
public void testSendTopicExchange() {
// 交换机名称
String exchangeName = "hmall.topic";
// 消息
String message = "喜报!孙悟空大战哥斯拉,胜!";
// 发送消息
rabbitTemplate.convertAndSend(exchangeName, "china.news", message);
}
消息接收:
@RabbitListener(queues = "topic.queue1")
public void listenTopicQueue1(String msg){
System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}
@RabbitListener(queues = "topic.queue2")
public void listenTopicQueue2(String msg){
System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}
✅ 应用场景
- 复杂消息分类系统
- 动态可扩展的路由规则(如日志系统)
六、headers(头部)交换机
✨ 特点
routingKey不再使用- 根据消息头属性进行路由(
headers字段) - 支持
x-match=all或x-match=any(全部匹配 / 任意匹配)
🧪 示例
Map<String, Object> headers = new HashMap<>();
headers.put("format", "pdf");
headers.put("type", "report");
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.headers(headers)
.build();
channel.basicPublish("headersExchange", "", props, body);
队列绑定时设置:
Map<String, Object> args = new HashMap<>();
args.put("x-match", "all");
args.put("format", "pdf");
args.put("type", "report");
channel.queueBind("reportQueue", "headersExchange", "", args);
✅ 应用场景
- 消息内容非常复杂,不适合用
routingKey - 使用
HTTP-style路由方式
七、总结对比
| 类型 | 是否用 routingKey | 是否支持通配符 | 路由依据 | 推荐场景 |
|---|---|---|---|---|
direct | ✅ 是 | ❌ 否 | routingKey 精准匹配 | 单类型消息精准投递 |
fanout | ❌ 否 | ❌ 否 | 广播所有队列 | 广播推送、群发消息 |
topic | ✅ 是 | ✅ 是 | 通配符匹配 | 多类型消息、日志系统 |
headers | ❌ 否 | ❌ 否 | headers匹配 | 复杂条件路由、企业集成系统 |

180

被折叠的 条评论
为什么被折叠?



