RabbitMQ—fanout(廣播模式)
一、什麼是fanout(廣播模式)
簡單的講,就是把交換機(Exchange)裏的消息發送給所有綁定該交換機的隊列,忽略routingKey。
由圖可知,生產者把消息發送到交換機後,由交換機發送給消費者隊列。消費者隊列如果想要接收到交換機裏的消息,那麼需要保證:隊列綁定的交換機名稱要和交換機一致,這個是廣播模式的關鍵,也是MQ後續所有模式最粗略的前提。
比如:
1)生產者聲明一個交換機(Exchange),交換機名稱爲“fanoutLogs”,類型爲廣播模式“fanout”,消息爲“Now you see me”;
channel.exchangeDeclare("fanoutLogs", "fanout");
2)消費者聲明一個隊列Q1,聲明一個交換機(名稱爲“fanoutLogs”,類型爲廣播模式”fanout“),最後隊列和交換機綁定;
channel.exchangeDeclare("fanoutLogs", "fanout");
channel.queueBind("Q1", "fanoutLogs", "");
3)消費者聲明另一個隊列Q2,聲明一個交換機(名稱爲”phantaciLogs“,類型爲廣播模式”fanout“),最後隊列與交換機綁定;
channel.exchangeDeclare("phantaciLogs", "fanout");
channel.queueBind("Q2", "phantaciLogs", "");
4)需注意,我們要先啓動聲明消費者,再啓動聲明生產者。否則先啓動生產者的話,exchange接到消息後發現沒有隊列對它感興趣,就任性的把消息給丟掉了;
5)Q1和Q2兩個消費者啓動後,啓動生產者。可以發現,和生產者交換機(Exchange)名稱相同的Q1正常接收到消息;Q2雖然也是廣播模式(fanout),但交換機名稱不同,所以未接收到消息。
RabbitMQ消息模型的核心思想(core idea): 生產者會把消息發送給RabbitMQ的交換中心(Exchange),Exchange的一側是生產者,另一側則是一個或多個隊列,由Exchange決定一條消息的生命週期–發送給某些隊列,或者直接丟棄掉。
二、代碼域
1. 生產者【FanoutBoss】
package com.iyungu.phantaci.test.rabbitmq;
import com.rabbitmq.client.*;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//廣播模式-消息生產者
public class FanoutBoss {
private static final Logger logger = Logger.getLogger(FanoutBoss.class);
public static void main(String[] args) {
//New一個RabbitMQ的連接工廠
ConnectionFactory factory = new ConnectionFactory();
//設置需要連接的RabbitMQ地址,這裏指向本機
factory.setHost("localhost");
try {
//嘗試獲取一個連接
Connection connection = factory.newConnection();
//嘗試創建一個channel
Channel channel = connection.createChannel();
String message = "當前時間爲:2018年8月6日14:25:14";
//聲明交換機(參數爲:交換機名稱; 交換機類型,廣播模式)
channel.exchangeDeclare("fanoutLogs", BuiltinExchangeType.FANOUT);
//消息發佈(參數爲:交換機名稱; routingKey,忽略。在廣播模式中,生產者聲明交換機的名稱和類型即可)
channel.basicPublish("fanoutLogs","", null,message.getBytes());
logger.info("********Message********:發送成功");
channel.close();
connection.close();
} catch (IOException |TimeoutException e) {
e.printStackTrace();
}
}
}
2. 消費者【FanoutWorker】
package com.iyungu.phantaci.test.rabbitmq;
import com.rabbitmq.client.*;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//廣播模式-消息消費者
public class FanoutWorker {
private static final Logger logger = Logger.getLogger(FanoutWorker.class);
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try {
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//交換機聲明(參數爲:交換機名稱;交換機類型)
channel.exchangeDeclare("fanoutLogs",BuiltinExchangeType.FANOUT);
//獲取一個臨時隊列
String queueName = channel.queueDeclare().getQueue();
//隊列與交換機綁定(參數爲:隊列名稱;交換機名稱;routingKey忽略)
channel.queueBind(queueName,"fanoutLogs","");
logger.info("********Waiting for messages********");
//這裏重寫了DefaultConsumer的handleDelivery方法,因爲發送的時候對消息進行了getByte(),在這裏要重新組裝成String
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
super.handleDelivery(consumerTag, envelope, properties, body);
String message = new String(body,"UTF-8");
logger.info("received:" + message);
}
};
//聲明隊列中被消費掉的消息(參數爲:隊列名稱;消息是否自動確認;consumer主體)
channel.basicConsume(queueName,true,consumer);
//這裏不能關閉連接,調用了消費方法後,消費者會一直連接着rabbitMQ等待消費
} catch (IOException |TimeoutException e) {
e.printStackTrace();
}
}
}
三、廣播模式效果
1. 先運行三個消費者,即【FanoutWorker】
控制檯效果圖如下,三個消費者等待接收消息
RabbitMQ網頁控制檯如下,可看到三個消費者隊列
2. 再運行一個生產者,即【FanoutBoss】
控制檯效果圖如下,一條消息發佈後,三個消費者都接收到了消息