Pub / Sub 订阅模式

特点是 一条消息可以给多个消费者接收了

首先创建订阅模式生产者发生一些代码变动:

package cn.dzz.pubSub;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; import java.nio.charset.StandardCharsets; public class PubSubInProducer { public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("192.168.2.121");
connectionFactory.setPort(ConnectionFactory.DEFAULT_AMQP_PORT); // 5672
connectionFactory.setVirtualHost("/dzz"); // 虚拟主机? 默认值 /
connectionFactory.setUsername("test"); // guest
connectionFactory.setPassword("123456"); // guest Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel(); /**
* 多了一个创建交换机的过程
* public DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException {
* return this.exchangeDeclare(exchange, type.getType(), durable, autoDelete, internal, arguments);
* }
* String exchange 交换机名称
* String type 交换机类型,这里换成枚举类型,方便查找 com.rabbitmq.client.BuiltinExchangeType
* DIRECT("direct"), 定向 简单模式 和 工作模式
* FANOUT("fanout"), 扇形 广播(通知给所有和这个交换机绑定的队列)
* TOPIC("topic"), 通配符 ?
* HEADERS("headers"); 参数匹配, 视频暂不讲解
* boolean durable 持久化
* boolean autoDelete 自动删除
* boolean internal 内部使用 一般false
* Map<String, Object> arguments
*
*
*/
String exchangeName = "test_fanout";
channel.exchangeDeclare(
exchangeName,
BuiltinExchangeType.FANOUT,
true,
false,
false,
null
); // 订阅模式案例需要两个队列支持
String queueName1 = "pub&sub - 1";
String queueName2 = "pub&sub - 2";
channel.queueDeclare(queueName1, true, false, false, null);
channel.queueDeclare(queueName2, true, false, false, null); /**
* 将交换机和队列绑定
* public com.rabbitmq.client.AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException {
* return this.queueBind(queue, exchange, routingKey, (Map)null);
* }
* String queue 队列名称
* String exchange 交换机名称
* String routingKey 路由键,绑定规则
* 如果是fanout模式, 设置""即可,默认就是给所有队列绑定
*
*/
channel.queueBind(queueName1, exchangeName, "");
channel.queueBind(queueName2, exchangeName, "");
// 发送消息
// for (int i = 0; i < 10; i++) {
// String body = "send sub&pub msg" + i;
// channel.basicPublish("", "work_queue", null, body.getBytes(StandardCharsets.UTF_8));
// } // 释放资源
// channel.close();
// connection.close();
} }

启动之后,可以发现在面板Exchange上面就能找到我们创建的交换机了

Queue面板上面有我们的两个订阅队列:

之后开始发送消息,注意下面发送消息的参数改动:

再次启动,将消息发送到RabbitMQ中

package cn.dzz.pubSub;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; import java.nio.charset.StandardCharsets; public class PubSubInProducer { public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("192.168.2.121");
connectionFactory.setPort(ConnectionFactory.DEFAULT_AMQP_PORT); // 5672
connectionFactory.setVirtualHost("/dzz"); // 虚拟主机? 默认值 /
connectionFactory.setUsername("test"); // guest
connectionFactory.setPassword("123456"); // guest Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel(); /**
* 多了一个创建交换机的过程
* public DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) throws IOException {
* return this.exchangeDeclare(exchange, type.getType(), durable, autoDelete, internal, arguments);
* }
* String exchange 交换机名称
* String type 交换机类型,这里换成枚举类型,方便查找 com.rabbitmq.client.BuiltinExchangeType
* DIRECT("direct"), 定向 简单模式 和 工作模式
* FANOUT("fanout"), 扇形 广播(通知给所有和这个交换机绑定的队列)
* TOPIC("topic"), 通配符 ?
* HEADERS("headers"); 参数匹配, 视频暂不讲解
* boolean durable 持久化
* boolean autoDelete 自动删除
* boolean internal 内部使用 一般false
* Map<String, Object> arguments
*
*
*/
String exchangeName = "test_fanout";
channel.exchangeDeclare(
exchangeName,
BuiltinExchangeType.FANOUT,
true,
false,
false,
null
); // 订阅模式案例需要两个队列支持
String queueName1 = "pub&sub - 1";
String queueName2 = "pub&sub - 2";
channel.queueDeclare(queueName1, true, false, false, null);
channel.queueDeclare(queueName2, true, false, false, null); /**
* 将交换机和队列绑定
* public com.rabbitmq.client.AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException {
* return this.queueBind(queue, exchange, routingKey, (Map)null);
* }
* String queue 队列名称
* String exchange 交换机名称
* String routingKey 路由键,绑定规则
* 如果是fanout模式, 设置""即可,默认就是给所有队列绑定
*
*/
channel.queueBind(queueName1, exchangeName, "");
channel.queueBind(queueName2, exchangeName, ""); // 发送消息
for (int i = 0; i < 10; i++) {
String body = "sending sub&pub msg " + i;
// 现在反过来, 交换机名字有了, 路由则默认了
channel.basicPublish(exchangeName, "", null
, body.getBytes(StandardCharsets.UTF_8));
} // 释放资源
channel.close();
connection.close();
} }

这样每个队列都有10条待送出的消息

创建两个订阅的消费者:

两个消费者接收都是一样的,注意切换队列名字

package cn.dzz.pubSubQueue;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets; public class PubSubQueueInConsumer1 { /**
* 工作队列 消费者
* @param args
*/
public static void main(String[] args) throws Exception{
ConnectionFactory connectionFactory = new ConnectionFactory(); connectionFactory.setHost("192.168.2.121");
connectionFactory.setPort(ConnectionFactory.DEFAULT_AMQP_PORT); // 5672
connectionFactory.setVirtualHost("/dzz"); // 虚拟主机? 默认值 /
connectionFactory.setUsername("test"); // guest
connectionFactory.setPassword("123456"); // guest Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel(); // 声明将不在需要
// channel.queueDeclare("work_queue", true, false, false, null); // 从生产者复制过来需要的队列名称
String queueName1 = "pub&sub - 1";
String queueName2 = "pub&sub - 2"
; Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("body(message) " + new String(body, StandardCharsets.UTF_8));
System.out.println("- - - - - over - - - - -");
}
}; channel.basicConsume(queueName1, true, consumer);
}
}

订阅的消费者1和2都能收到同样的消息:

"C:\Program Files (x86)\Java\jdk1.8.0_291\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=58116:C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\charsets.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\deploy.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\access-bridge-32.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\cldrdata.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\dnsns.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\jaccess.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\jfxrt.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\localedata.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\nashorn.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunec.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunjce_provider.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunmscapi.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\sunpkcs11.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\ext\zipfs.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\javaws.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jce.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jfr.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jfxswt.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\jsse.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\management-agent.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\plugin.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\resources.jar;C:\Program Files (x86)\Java\jdk1.8.0_291\jre\lib\rt.jar;C:\Users\Administrator\IdeaProjects\RabbitMQ\ConsumerService\target\classes;C:\Users\Administrator\.m2\repository\com\rabbitmq\amqp-client\5.6.0\amqp-client-5.6.0.jar;C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar" cn.dzz.pubSubQueue.PubSubQueueInConsumer2
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
body(message) sending sub&pub msg 0
- - - - - over - - - - -
body(message) sending sub&pub msg 1
- - - - - over - - - - -
body(message) sending sub&pub msg 2
- - - - - over - - - - -
body(message) sending sub&pub msg 3
- - - - - over - - - - -
body(message) sending sub&pub msg 4
- - - - - over - - - - -
body(message) sending sub&pub msg 5
- - - - - over - - - - -
body(message) sending sub&pub msg 6
- - - - - over - - - - -
body(message) sending sub&pub msg 7
- - - - - over - - - - -
body(message) sending sub&pub msg 8
- - - - - over - - - - -
body(message) sending sub&pub msg 9
- - - - - over - - - - -

【RabbitMQ】03 订阅模式的更多相关文章

  1. RabbitMQ 之 订阅模式 Publish/Subscribe

    模型图 我们之前学习的都是一个消息只能被一个消费者消费,那么如果我想发一个消息 能被多个消费者消费,这时候怎么办? 这时候我们就得用到了消息中的发布订阅模型 在前面的教程中,我们创建了一个工作队列,都 ...

  2. .Net下RabbitMQ发布订阅模式实践

    一.概念AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计.消息中间件主要用于组件之间的解耦,消息的发 ...

  3. Rabbitmq(4) 订阅模式

    p;发送者 x: 交换机 消息队列 c: 接收者 ------------------------------------------------------------------------ 发送 ...

  4. RabbitMQ 发布订阅

    互联网公司对消息队列是深度使用者,因此需要我们了解消息队列的方方面面,良好的设计及深入的理解,更有利于我们对消息队列的规划. 当前我们使用消息队列中发现一些问题: 1.实际上是异步无返回远程调用,由发 ...

  5. RabbitMQ/JAVA (发布/订阅模式)

    发布/订阅模式即生产者将消息发送给多个消费者. 下面介绍几个在发布/订阅模式中的关键概念-- 1. Exchanges (转发器) 可能原来我们都是基于一个队列发送和接收消息.现在介绍一下完整的消息传 ...

  6. python使用rabbitMQ介绍三(发布订阅模式)

    一.模式介绍 在前面的例子中,消息直接发送到queue中. 现在介绍的模式,消息发送到exchange中,消费者把队列绑定到exchange上. 发布-订阅模式是把消息广播到每个消费者,每个消费者接收 ...

  7. RabbitMQ简单应用の订阅模式

    订阅模式 公众号-->订阅之后才会收到相应的文章. 解读: 1.一个生产者,多个消费者 2.每个消费者都有自己的队列 3.生产者没有将消息直接发送到队列里,而是发送给了交换机(转发器)excha ...

  8. Go RabbitMQ(三)发布订阅模式

    RabbitMQ 在上一节中我们创建了工作队列,并且假设每一个任务都能够准确的到达对应的worker.在本节中我们将介绍如何将一个消息传递到多个消费者,这也就是所说的发布订阅模式 为了验证该模式我们使 ...

  9. RabbitMQ指南之三:发布/订阅模式(Publish/Subscribe)

    在上一章中,我们创建了一个工作队列,工作队列模式的设想是每一条消息只会被转发给一个消费者.本章将会讲解完全不一样的场景: 我们会把一个消息转发给多个消费者,这种模式称之为发布-订阅模式. 为了阐述这个 ...

  10. RabbitMQ六种队列模式-发布订阅模式

    前言 RabbitMQ六种队列模式-简单队列RabbitMQ六种队列模式-工作队列RabbitMQ六种队列模式-发布订阅 [本文]RabbitMQ六种队列模式-路由模式RabbitMQ六种队列模式-主 ...

随机推荐

  1. 穿透 wsl 和 ssh, 新版本 neovim 跨设备任意复制,copy anywhere!

    获得更好的阅读体验,欢迎查看原文:穿透 wsl 和 ssh, 新版本 neovim 跨设备任意复制,copy anywhere! 1. 创作动机 最近一个星期,我入坑了 neovim, 然后开始配置各 ...

  2. 采用Dapr 的IoT 案例

    CNCF 发布了一篇Dapr 的IoT 案例:Tempestive uses Dapr and K8s to track IoT messages | CNCF.Tempestive 是一家物联网解决 ...

  3. 算法学习笔记(30):Kruskal 重构树

    Kruskal 重构树 这是一种用于处理与最大/最小边权相关的一个数据结构. 其与 kruskal 做最小生成树的过程是类似的,我们考虑其过程: 按边权排序,利用并查集维护连通性,进行合并. 如果我们 ...

  4. 剑指Offer-60.把二叉树打印成多行(C++/Java)

    题目: 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 分析: 层次打印二叉树,在打印二叉树结点的同时,保存好结点的左右孩子,不断的重复打印,直到需要打印的数组为空即可. 程序: C ...

  5. kettle从入门到精通 第四十二课 kettle 1对多表拆分同步

    1.在有的业务场景中,会涉及一对多表拆分同步的业务场景,也就是说原表是一张表,将原表字段进行拆分放入目标库中的多张表,如下面的示例将表student_third中的数据 同步到student.teac ...

  6. Python + redis操作Redis数据库

    Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...

  7. SMB3.0多通道叠加双网卡提速

    SMB3.0多通道叠加双网卡提速 (双网卡.多网卡,NAS,局域网共享速度) WIN8及以上是默认开启的.(WIN10.WIN11 默认开启) 只需要同规格的网卡,比如你一张是1Gbps的,另一张网卡 ...

  8. C#字符串截取分割方法

    字符串操作:分割 Split.连接数组 Join.拼接 Format.截取 Substring.替换 Replace.左填充 PadLeft.右填充 PadRight.删除 Remove 1 //分割 ...

  9. spring boot jpa 进行通用多条件动态查询和更新 接口

    原因: jpa 没有类似于mybatis的那种 拼接sql的方式 想动态更新 需要使用 CriteriaUpdate的方式 去一直拼接,其实大多数场景只要传入一个非空实体类,去动态拼接sql 1.定义 ...

  10. 图最短路径之BellmanFord

    Bellman–Ford Algorithm 算法参考地址:Bellman–Ford Algorithm | DP-23 - GeeksforGeeks 算法的简介 在图中给定一个图形和一个源顶点 s ...