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. Java synchronized与ReentrantLock的区别

    synchronized与ReentrantLock的区别 synchronized是一个关键字,ReentrantLock是一个类 synchronized修饰代码块和方法,ReentrantLoc ...

  2. kettle从入门到精通 第四十九课 ETL之kettle 自定义插件01

    1.kettle插件是什么 kettle本身有足够多的转换或者job步骤,但是依然不能覆盖所有的业务场景,所以Kettle 自定义插件在有些独特的业务场景可以大显身手. Kettle的插件架构使得我们 ...

  3. 通过JS来触发<a>链接来实现图片下载

    function downloadImg(){ var url = '实际情况的图片URL'; // 获取图片地址 var a = document.createElement('a'); // 创建 ...

  4. Vue 3与ESLint、Prettier:构建规范化的前端开发环境

    title: Vue 3与ESLint.Prettier:构建规范化的前端开发环境 date: 2024/6/11 updated: 2024/6/11 publisher: cmdragon exc ...

  5. redis高可用哨兵篇

    https://redis.io/docs/manual/sentinel/#sentinels-and-replicas-auto-discovery 官网资料 在上文主从复制的基础上,如果注节点出 ...

  6. Redis的特点什么是?

    a.支持多种数据结构,如 string(字符串). list(双向链表).dict(hash表).set(集合).zset(排序set).hyperloglog(基数估算) b.支持持久化操作,可以进 ...

  7. 解锁LLMs的“思考”能力:Chain-of-Thought(CoT) 技术推动复杂推理的新发展

    解锁LLMs的"思考"能力:Chain-of-Thought(CoT) 技术推动复杂推理的新发展 1.简介 Chain-of-Thought(CoT)是一种改进的Prompt技术, ...

  8. aspose word与pdf互转

    aspose word与pdf互转 package com.example.core.mydemo.aspose; import com.aspose.words.Document; import c ...

  9. 【原创】EtherCAT主站IgH解析(二)-- Linux/Windows/RTOS等多操作系统IgH EtherCAT主站移植指南

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 前言 目前,EtherCAT商用主站有:Aconti ...

  10. Pycharm import faker 和 colorlog提示“No module name faker/colorlog”

    问题: Pycharm import faker / colorlog,下划线爆红,提示"No module name faker/colorlog" 排查,检查pycharm 该 ...