RabbitMQ---订阅模型-Fanout

1、 订阅模型-Fanout

Fanout,也称为广播。

流程图:

在广播模式下,消息发送流程是这样的:

1) 可以有多个消费者

2) 每个消费者有自己的queue(队列)

3) 每个队列都要绑定到Exchange(交换机)

4) 生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。

5) 交换机把消息发送给绑定过的所有队列

6) 队列的消费者都能拿到消息。实现一条消息被多个消费者消费

1.1、生产者

两个变化:

1) 声明Exchange,不再声明Queue

2) 发送消息到Exchange,不再发送到Queue

java 复制代码
public class Send {
   private final static String EXCHANGE_NAME = "fanout_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明exchange,指定类型为fanout
       channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
       // 消息内容
       String message = "Hello everyone";
       // 发布消息到Exchange
       channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes());
       System.out.println(" [生产者] Sent '" + message + "'");
       channel.close();
       connection.close();
   }
}

1.2、消费者1

java 复制代码
public class Recv {
   private final static String QUEUE_NAME = "fanout_exchange_queue_1";
   private final static String EXCHANGE_NAME = "fanout_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明队列
       channel.queueDeclare(QUEUE_NAME, false, false, false, null);
       // 绑定队列到交换机
       channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
       // 定义队列的消费者
       DefaultConsumer consumer = new DefaultConsumer(channel) {
           // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
           @Override
           public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties, byte[] body) throws IOException {
               // body 即消息体
               String msg = new String(body);
               System.out.println(" [消费者1] received : " + msg + "!");
           }
       };
       // 监听队列,自动返回完成
       channel.basicConsume(QUEUE_NAME, true, consumer);
   }
}

1.3、 消费者2

java 复制代码
public class Recv2 {
   private final static String QUEUE_NAME = "fanout_exchange_queue_2";
   private final static String EXCHANGE_NAME = "fanout_exchange_test";
   public static void main(String[] argv) throws Exception {
       // 获取到连接
       Connection connection = ConnectionUtil.getConnection();
       // 获取通道
       Channel channel = connection.createChannel();
       // 声明队列
       channel.queueDeclare(QUEUE_NAME, false, false, false, null);
       // 绑定队列到交换机
       channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "");
       // 定义队列的消费者
       DefaultConsumer consumer = new DefaultConsumer(channel) {
           // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
           @Override
           public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                   byte[] body) throws IOException {
               // body 即消息体
               String msg = new String(body);
               System.out.println(" [消费者2] received : " + msg + "!");
           }
       };
       // 监听队列,手动返回完成
       channel.basicConsume(QUEUE_NAME, true, consumer);
   }
}

1.4、 测试

我们应该先启动生产者,否则,先启动消费者时,由于要绑定交换机,此时,交换机并不存在所以会报错。

我们运行两个消费者,然后发送1条消息:


相关推荐
原来是猿4 分钟前
TCP Echo Server 深度解析:从单进程到线程池的演进之路(上)
服务器·网络·tcp/ip
躺不平的理查德5 分钟前
Shell逻辑判断备忘录
运维·服务器·git
skywalk816315 分钟前
Trae生成的中文编程语言关键字(如“定“、“函“、“印“等)需要和标识符之间用 空格 隔开,以确保正确识别
服务器·开发语言·编程
请你喝可乐16 分钟前
AI Agent Skill 高阶使用指南:从入门到精通
后端
用户9623779544816 分钟前
代码审计 | Struts2 —— S2-016 OGNL 注入原理
后端
9号达人23 分钟前
为什么你应该在 MQ 里用多个消费者,而不是一个
java·后端·架构
焦糖玛奇朵婷25 分钟前
健身房预约小程序开发、设计
java·大数据·服务器·前端·小程序
阿星做前端43 分钟前
重度 AI 编程用户的一天:我怎么把 Claude Code / Codex 工作流搬进浏览器工作台
前端·javascript·后端
代码羊羊1 小时前
Rust 类型转换全方位通俗易懂指南(as、TryInto、强制转换、Transmute)
后端·rust
jay神1 小时前
基于SpringBoot的宠物生命周期信息管理系统
java·数据库·spring boot·后端·web开发·宠物·管理系统