Fanout 交换机
Fanout交换机将消息广播到所有绑定队列,忽略路由键实现发布订阅模式。
定义
Fanout交换机接收消息后,无条件将消息副本投递到所有与其绑定的队列,路由键被完全忽略。这是最快的交换机类型,适用于一对多消息分发场景。
核心机制
广播流程
- 生产者发送消息到Fanout交换机(路由键可为空)
- 交换机接收消息后,获取所有绑定队列列表
- 为每个绑定队列创建消息副本并投递
- 各队列独立消费消息,互不影响
声明与绑定
Java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class FanoutExchangeExample {
private static final String EXCHANGE_NAME = "broadcast_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
// 声明Fanout交换机
channel.exchangeDeclare(EXCHANGE_NAME, "fanout", true);
// 声明三个队列
channel.queueDeclare("queue_email", true, false, false, null);
channel.queueDeclare("queue_sms", true, false, false, null);
channel.queueDeclare("queue_webhook", true, false, false, null);
// 绑定所有队列到Fanout交换机(路由键被忽略)
channel.queueBind("queue_email", EXCHANGE_NAME, "");
channel.queueBind("queue_sms", EXCHANGE_NAME, "");
channel.queueBind("queue_webhook", EXCHANGE_NAME, "");
// 发布消息(路由键任意,通常传空字符串)
String message = "Order created: #12345";
channel.basicPublish(EXCHANGE_NAME, "", null,
message.getBytes("UTF-8"));
System.out.println("Broadcast message sent: " + message);
}
}
}
临时队列广播
适用于日志收集、事件通知等只需运行时接收消息的场景:
Java
import com.rabbitmq.client.*;
import java.io.IOException;
public class FanoutTemporaryConsumer {
private static final String EXCHANGE_NAME = "broadcast_logs";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(EXCHANGE_NAME, "fanout", true);
// 声明临时队列(非持久化、独占、自动删除)
String queueName = channel.queueDeclare().getQueue();
// 绑定到Fanout交换机
channel.queueBind(queueName, EXCHANGE_NAME, "");
System.out.println("Listening for broadcast messages...");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println("Received: " + message);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume(queueName, false, deliverCallback, consumerTag -> {});
}
}
注意事项
- Fanout交换机忽略所有路由键,消息必然投递到所有绑定队列
- 性能最高(无需路由计算),适用于广播、通知、事件分发
- 无法实现选择性投递,若需过滤应改用Direct或Topic交换机
- 临时队列断开连接后自动删除,适合日志收集等短暂订阅场景
- 绑定多个队列时,交换机为每个队列创建独立消息副本,内存占用与队列数成正比
要点总结
- Fanout交换机将消息广播到所有绑定队列,路由键无效
- 适用于发布订阅、事件通知、日志收集等一对多场景
- 性能最优,无需路由匹配计算
- 支持临时队列实现运行时动态订阅
- 无法选择性过滤消息,需过滤时应使用其他交换机类型
文章存放路径:D:\git2\jwdev\articles\RABBITMQ\进阶\交换机类型详解\Fanout 交换机.md
📝 发现内容有误?点击此处直接编辑