开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情
4.5 第三种模型(fanout)
fanout 扇出 也称为广播
在广播模式下,消息发送流程是这样的:
- 可以有多个消费者
- 每个消费者有自己的queue(队列)
- 每个队列都要绑定到Exchange(交换机)
- 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
- 交换机把消息发送给绑定过的所有队列
- 队列的消费者都能拿到消息。实现一条消息被多个消费者消费
1. 开发生产者
//声明交换机
channel.exchangeDeclare("logs","fanout");//广播 一条消息多个消费者同时消费
//发布消息
channel.basicPublish("logs","",null,"hello".getBytes());
生产者类:
public class Provider {
public static void main(String[] args) throws IOException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 创建通道对象
Channel channel = connection.createChannel();
// 将通道声明指定的交换机 交换机名字 交换机类型fanout:广播类型 注;交换机不存在的话会自动创建
channel.exchangeDeclare("logs", "fanout"); // 广播的话交换机类型必须写 fanout
// 发送消息 交换机名字 路由key 消息持久化特性 消息
channel.basicPublish("logs", "", null, "fanout type message".getBytes());
// 释放资源
RabbitMQUtils.closeConnectionAndChanel(channel, connection);
}
}
2. 开发消费者-1
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,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));
}
});
消费者1类:
public class Consumer1 {
public static void main(String[] args) throws IOException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取通道对象
Channel channel = connection.createChannel();
// 通道绑定交换机 交换机名字 交换机类型
channel.exchangeDeclare("logs", "fanout"); // 消费者一定要和生产者对应上
// 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机和队列(通过通道把它俩组合到一起) 队列名字 哪个交换机 路由key
channel.queueBind(queueName, "logs", "");
// 消费消息 队列名字 是否自动确认 回调接口用来消费消息
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));
}
});
}
}
3. 开发消费者-2
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者2: "+new String(body));
}
});
消费者2类:
public class Consumer2 {
public static void main(String[] args) throws IOException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取通道对象
Channel channel = connection.createChannel();
// 通道绑定交换机 交换机名字 交换机类型
channel.exchangeDeclare("logs", "fanout"); // 消费者一定要和生产者对应上
// 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机和队列(通过通道把它俩组合到一起) 队列名字 哪个交换机 路由key
channel.queueBind(queueName, "logs", "");
// 消费消息 队列名字 是否自动确认 回调接口用来消费消息
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("消费者2:" + new String(body));
}
});
}
}
4.开发消费者-3
//绑定交换机
channel.exchangeDeclare("logs","fanout");
//创建临时队列
String queue = channel.queueDeclare().getQueue();
//将临时队列绑定exchange
channel.queueBind(queue,"logs","");
//处理消息
channel.basicConsume(queue,true,new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("消费者3: "+new String(body));
}
});
消费者3类:
public class Consumer3 {
public static void main(String[] args) throws IOException {
// 获取连接对象
Connection connection = RabbitMQUtils.getConnection();
// 获取通道对象
Channel channel = connection.createChannel();
// 通道绑定交换机 交换机名字 交换机类型
channel.exchangeDeclare("logs", "fanout"); // 消费者一定要和生产者对应上
// 临时队列的名字(没有必要创建持久队列,减轻Rabbitmq中队列的数量)
String queueName = channel.queueDeclare().getQueue();
// 绑定交换机和队列(通过通道把它俩组合到一起) 队列名字 哪个交换机 路由key
channel.queueBind(queueName, "logs", "");
// 消费消息 队列名字 是否自动确认 回调接口用来消费消息
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("消费者3:" + new String(body));
}
});
}
}