扇型交換機(funout exchange)將消息路由給綁定到它身上的所有隊列,而不理會綁定的路由鍵。如果 N 個隊列綁定到某個扇型交換機上,當有消息發送給此扇型交換機時,交換機會將消息的拷貝分別發送給這所有的 N 個隊列。
因爲扇型交換機投遞消息的拷貝到所有綁定到它的隊列,所以它的應用案例都極其相似:
大規模多用戶在線(MMO)遊戲可以使用它來處理排行榜更新等全局事件。
體育新聞網站可以用它來近乎實時地將比分更新分發給移動客戶端。
分發系統使用它來廣播各種狀態和配置更新。
在羣聊的時候,它被用來分發消息給參與羣聊的用戶。(AMQP 沒有內置 presence 的概念,因此 XMPP 可能會是個更好的選擇)。
扇型交換機圖例:
上圖所示,生產者(P)生產消息 1 ,將消息 1 推送到 Exchange,由於 Exchange Type=fanout ,這時候會遵循 fanout exchange的路由規則,將消息推送到所有與它綁定的 Queue,也就是圖上的兩個 Queue, 最後由監聽對應Queue的消費者消費 。
package com.kaven.rabbitmq.exchange.fanoutExchange;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class FanoutProducer {
// 自己服務器的IP
private static String ip = "IP";
// RabbitMQ啓動的默認端口,也是應用程序進行連接RabbitMQ的端口
private static int port = 5672;
// RabbitMQ有一個 "/" 的虛擬主機
private static String virtualHost = "/";
// fanout exchange ,RabbitMQ提供的fanout exchange
private static String exchangeName = "amq.fanout";
// exchange type
private static String exchangeType= "fanout";
// 交換機路由的routingKey
private static String routingKey = "";
public static void main(String[] args) throws IOException, TimeoutException {
// 1 創建一個連接工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(ip);
connectionFactory.setPort(port);
connectionFactory.setVirtualHost(virtualHost);
// 2 創建連接
Connection connection = connectionFactory.newConnection();
// 3 創建Channel
Channel channel = connection.createChannel();
// 4 發送消息
String msg = "RabbitMQ:Fanout Exchange 發送數據";
channel.basicPublish(exchangeName ,routingKey ,null, msg.getBytes());
// 5 關閉連接
channel.close();
connection.close();
}
}
消費端:
package com.kaven.rabbitmq.exchange.fanoutExchange;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class FanoutConsumer {
// 自己服務器的IP
private static String ip = "IP";
// RabbitMQ啓動的默認端口,也是應用程序進行連接RabbitMQ的端口
private static int port = 5672;
// RabbitMQ有一個 "/" 的虛擬主機
private static String virtualHost = "/";
// fanout exchange ,RabbitMQ提供的fanout exchange
private static String exchangeName = "amq.fanout";
// exchange type
private static String exchangeType= "fanout";
// 隊列名
private static String queueName = "queue";
// 隊列與交換機綁定的routingKey
private static String routingKey = "test";
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
// 1 創建一個連接工廠
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(ip);
connectionFactory.setPort(port);
connectionFactory.setVirtualHost(virtualHost);
// 2 創建連接
Connection connection = connectionFactory.newConnection();
// 3 創建Channel
Channel channel = connection.createChannel();
// 4 定義Queue ,將Queue綁定到direct exchange
channel.queueDeclare(queueName,true , false , false , null);
channel.queueBind(queueName , exchangeName , routingKey);
// 5 創建消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
// 6 設置
channel.basicConsume(queueName , true , consumer);
// 7 接收消息
while(true){
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println(msg);
}
}
}
測試
因爲這裏使用的是RabbitMQ提供給我們的fanout exchange,所以我們無需自己定義。
因爲交換機已經定義好了,所以無論先啓動生產端還是消費端,消費端都可以成功收到消息。
消費端輸出如下:
RabbitMQ:Fanout Exchange 發送數據