上一篇介紹了直連隊列模式,但實際生產中生產者不直接發送消息到隊列,而是發送到交換機,由交換機根據路由規則分發到隊列。本文深入講解三種核心交換機類型:Fanout、Direct、Topic。
廣播模式:消息發送到交換機,綁定該交換機的所有隊列都會收到相同消息。
public class EmitLog {
private static final String EXCHANGE_NAME = "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");
for (int i = 0; i < 5; i++) {
String message = "Hello World" + i;
channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
System.out.println("EmitLog Sent '" + message + "'");
}
channel.close();
connection.close();
}
}
public class ReceiveLogs1 {
private static final String EXCHANGE_NAME = "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");
String queueName = channel.queueDeclare().getQueue(); // 隨機隊列名
channel.queueBind(queueName, EXCHANGE_NAME, "");
System.out.println("ReceiveLogs1 Waiting for messages");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope,
AMQP.BasicProperties properties, byte[] body) throws IOException {
String message = new String(body, "UTF-8");
System.out.println("ReceiveLogs1 Received '" + message + "'");
}
};
channel.basicConsume(queueName, true, consumer);
}
}
根據 Routing Key 精確匹配路由到指定隊列,支持多消費者分工處理不同級別消息。
public class RoutingSendDirect {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] ROUTING_KEYS = {"info", "warning", "error"};
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, "direct");
for (String routingKey : ROUTING_KEYS) {
String message = "RoutingSendDirect Send the message level:" + routingKey;
channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes());
System.out.println("RoutingSendDirect Send " + routingKey + "':'" + message);
}
channel.close();
connection.close();
}
}
public class ReceiveLogsDirect1 {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] ROUTING_KEYS = {"info", "warning"};
// ... 綁定多個 routingKey 到同一隊列
}
public class ReceiveLogsDirect2 {
private static final String EXCHANGE_NAME = "direct_logs";
private static final String[] ROUTING_KEYS = {"error"};
// ... 只綁定 error routingKey
}
支持通配符模糊匹配:* 匹配單個詞,# 匹配零個或多個詞。
quick.orange.rabbitlazy.orange.elephantquick.orange.fox*.orange.*:匹配中間為 orange 的所有路由*.*.rabbit:匹配最後為 rabbit 的三段式路由lazy.#:匹配以 lazy 開頭的所有路由| 交換機類型 | 路由規則 | 適用場景 |
|---|---|---|
| Fanout | 廣播,無視 Routing Key | 日志廣播、事件通知 |
| Direct | 精確匹配 Routing Key | 任務分發、級別路由 |
| Topic | 通配符模糊匹配 | 多維度路由、複雜業務 |
掌握三種交換機模式,能靈活設計消息路由拓撲,滿足不同業務場景需求。