Fanout 广播模型
广播模型在生活中是非常常见:
只要你是这个班的学生,在集体活动的时候,老师会在你们班教室中宣布事请,
这样,在这个教室中的所有学生都收到这个消息。
当然,不在这个教室的学生,这个时候就接收不到这个消息了。也就是说你不在一个频道
目录
预览
模型图
把教师看作是消息的生产者
把教室看作是路由
把学生看作是消费者
在教室的学生(绑定到路由的消费者队列)就能接收到广播的数据了
广播模型特点
从这张模型图上不难看出,广播模型的特点
-
可以有多个消费者
-
每个消费者都有自己的 Queue(队列)
-
每个队列都要绑定到 Exchange (交换机)
-
生产者发送的消息,只能发送到交换机,减缓及来决定要发送给那个队列,生产者无法决定
-
交换机把消息发送给绑定的所有队列
-
队列的消费者都能拿到消息,实现一条消息被多个消费者消费
下面我们使用代码去实现
代码实现
首先创建工具类 ConnectionUtil 用于创建和关闭连接
Step1:工具类 COnnectionUtil
public class ConnectionUtil {
/** Ip 地址 */
private static final String IP_ADDRESS = "127.0.0.1";
/** 固定端口 */
private static final int PORT = 5672;
// TODO 改成你自己的用户名
/** 用户名 */
private static final String USER_NAME = "root";
// TODO 改成你自己的密码
/** 密码 */
private static final String PASSWORD = "dcpnet";
/**
* 获取连接
* @return 连接
* @throws IOException IOException
* @throws TimeoutException TimeOutException
*/
public static Connection getConnection() throws IOException, TimeoutException {
/** 创建连接工厂 */
ConnectionFactory connectionFactory = new ConnectionFactory();
// 设置连接工厂属性
// IP 地址
connectionFactory.setHost(IP_ADDRESS);
// 端口
connectionFactory.setPort(PORT);
// 用户名
connectionFactory.setUsername(USER_NAME);
// 密码
connectionFactory.setPassword(PASSWORD);
// 创建新的连接并且返回
return connectionFactory.newConnection();
}
/**
* 关闭资源
* @param connection 连接
* @param channel 信道
*/
public static void close(Connection connection, Channel channel){
try {
channel.close();
connection.close();
} catch (IOException | TimeoutException e) {
e.printStackTrace();
}
}
}
Step2:创建路由器
方式一:在web管理页面创建
方式二:使用代码创建
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 创建信道
Channel channel = connection.createChannel();
// 声明交换机 参数一:交换机的名字 参数二:交换机的类型 fanout(广播类型)
channel.exchangeDeclare("log","fanout");
Step3:创建生产者
public class ProducerClient {
public static void main(String[] args) throws Exception{
// 获取连接
Connection connection = ConnectionUtil.getConnection();
// 创建信道
Channel channel = connection.createChannel();
// 声明交换机 参数一:交换机的名字 参数二:交换机的类型 fanout(广播类型)
// channel.exchangeDeclare("log","fanout");
// 发布消息 param1:交换机的名字 param2:路由的键值 param3: param4:消息内容的字节数组
channel.basicPublish("log","p1",null,(new Date()+"生产者消息").getBytes());
// 关闭信道(channel)和连接(connection)
ConnectionUtil.close(connection,channel);
}
}
Step4:创建消费者
public class ConsumerClient1 {
public static void main(String[] args) throws Exception{
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 创建一个临时队列
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName,"log","p1");
channel.basicConsume(queueName,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(">[消费者1] 接收到数据" + new String(body));
}
});
}
}
将消费者复制粘贴几份
Step5:运行
先将几个消费者 Consumer 运行起来,创建临时队列绑定到路由器。
然后运行生产者 Producer
可以看到几个消费者都接收到了这一条消息