RabbitMQ系列学习笔记(八)--发布订阅模式

文章目录

  • 一、发布订阅模式原理
  • 二、发布订阅模式实战
    • 1、消费者代码
    • 2、生产者代码
    • 3、查看运行结果

本文参考:
尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq
RabbitMQ 详解
Centos7环境安装Erlang、RabbitMQ详细过程(配图)

一、发布订阅模式原理

image.png
在开发过程中,有一些消息需要不同消费者进行不同的处理,如电商网站的同一条促销信息需要短信发送、邮件发送、站内信发送等。此时可以使用发布订阅模式(Publish/Subscribe),其工作原理如下:

  • 生产者将消息发送给交换机,交换机将消息转发到绑定此交换机的 每个队列 中。
  • 工作队列模式的交换机只能将消息发送给一个队列,发布订阅模式的交换机能将消息发送给多个队列。
  • 发布订阅模式使用 fanout 交换机。

Fanout这种类型非常简单。它是将接收到的所有消息广播到它知道的所有队列中。在系统中可以查看到默认的一些exchange类型,其中就包括fanout类型交换机。
image.png

二、发布订阅模式实战

1、消费者代码

在发布订阅模式下,需要使用fanout类型的交换机,可以选择通过channel.exchangeDeclare()创建,指定类型为fanout,并且需要将交换机与队列进行绑定,形成绑定关系,这样生产者在发送消息到交换机以后,fanout交换机才会把该消息广播发送到各个具有绑定关系的队列。
消费者01代码如下:

/**
 * Description: 发布订阅模式消费者01
 */
public class ReceiveLogs01 {
    //设置要创建的交换机的名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
    	//创建fanout交换机
        /**
         * 参数1:交换机名
         * 参数2:交换机类型
         * 参数3:交换机是否持久化
         */
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false);
    	/** 
        * 生成一个临时的队列 队列的名称是随机的 
        * 当消费者断开和该队列的连接时,队列自动删除,防止无用队列占用空间
        */ 
        String queueName = channel.queueDeclare().getQueue();
    	//将交换机与队列进行绑定(binding)
        /**
         * 参数1:队列名
         * 参数2:交换机名
         * 参数3:路由关键字,发布订阅模式写""空串即可
         */
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("等待接收消息,把接收到的消息打印在屏幕上......");
    	//接收消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogs01控制台打印接收到的消息: " + message);
            }
        });
    }
}

消费者02代码如下:

/**
 * Description: 发布订阅模式消费者02
 */
public class ReceiveLogs02 {
    //设置要创建的交换机的名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
    	
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout", false);
    	
        String queueName = channel.queueDeclare().getQueue();
    	
        channel.queueBind(queueName, EXCHANGE_NAME, "");
        System.out.println("等待接收消息,把接收到的消息打印在屏幕上......");
    	//接收消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                String message = new String(body, "UTF-8");
                System.out.println("ReceiveLogs02控制台打印接收到的消息: " + message);
            }
        });
    }
}

2、生产者代码

由于在消费者中已经完成交换机声明,队列创建及二者之间的绑定关系,因此生产者部分的代码较为简单,只需要在发送消息时指定好前面创建的交换机名称即可。

/**
 * Description: 发布订阅模式生产者
 */
public class EmitLog {
    //交换机名称
    private static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        
        //发送消息
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String message = sc.nextLine();
            
            //参数1:指定交换机名称
            //参数2:指定routingkey,发布订阅模式写""空串即可
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
            System.out.println("生产者发出消息" + message);
        }
        //关闭资源
        channel.close();
    }
}

3、查看运行结果

将ReceiveLogs01和ReceiveLogs02启动,等待接收消息,再启动生产者,通过控制台发送消息。
image.png
消息发送完毕以后,查看两个消费者都接收到了同样的消息,类似广播,而非之前的互斥接收。
image.png
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/896617.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大数据治理的核心思想

目录 ​编辑1.1 大数据治理的定义与重要性 1.2 大数据治理的关键要素 1.2.1 数据质量管理 1.2.2 数据安全管理 1.2.3 合规性管理 1.2.4 数据共享与协作 1.2.5 数据驱动的决策 二、对未来趋势的看法 2.1 技术发展趋势 2.1.1 人工智能与机器学习 2.1.2 云计算与边缘计…

Python数据处理工具笔记 - matplotlib, Numpy, Pandas

matplotlib, Numpy, Pandas 由于有很多例子是需要运算后的图表看着更明白一些,很明显csdn不支持 所以用谷歌的Colab(可以理解为白嫖谷歌的云端来运行的jupyter notebook)来展示: Colab链接(需要梯子):Python数据挖掘 当然如果实在没有梯子&…

算法打卡 Day43(动态规划)-背包问题 + 分割等和子集

文章目录 0-1 背包问题理论基础0-1 背包问题滚动数组Leetcode 416-分割等和子集题目描述解题思路 0-1 背包问题理论基础 0-1 背包一般的题目要求是给定不同重量不同价值的物品,每个物品只有一个,已知背包中最大的负重,求在此限制条件下背包中…

达那福发布新品音致系列:以顶尖降噪技术,开启清晰聆听新篇章

近日,国际知名助听器品牌达那福推出其最新研发的音致系列助听器。该系列产品旨在通过顶尖的声音处理技术,直面助听器市场中普遍存在的挑战——如何在噪声环境中提供清晰的语音辨识。 根据助听器行业协会2022年的调查数据,高达86%的佩戴者认为…

数据结构——二叉树的基本操作及进阶操作

前言 介绍 🍃数据结构专区:数据结构 参考 该部分知识参考于《数据结构(C语言版 第2版)》116 ~ 122页 及 《数据结构教程》201 ~ 213页 重点 树的基本实现并不难,重点在于对递归的理解才是树这部分知识带来的最大收…

jmeter学习(8)界面的使用

1、新建test plan 3、 打开文件 4、保存 5、剪切 6、复制 7、粘贴 8、所有线程组展开 9、所有线程组收缩 10、置灰,操作后无法使用 11、执行 13、清空当前线程组结果 14、清空所有线程组结果 15、函数助手 搜索,可以用于搜索某个请求&#x…

Java基于微信小程序的健身小助手打卡预约教学系统(源码+lw+部署文档+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…

使用OpenCV进行视频边缘检测:案例Python版江南style

1. 引言 本文将演示如何使用OpenCV库对视频中的每一帧进行边缘检测,并将结果保存为新的视频文件。边缘检测是一种图像处理技术,它可以帮助我们识别出图像中不同区域之间的边界。在计算机视觉领域,这项技术有着广泛的应用,比如物体…

登录时用户名密码加密传输(包含前后端代码)

页面输入用户名密码登录过程中,如果没有对用户名密码进行加密处理,可能会导致传输过程中数据被窃取,就算使用https协议,在浏览器控制台的Request Payload中也是能直接看到传输的明文,安全感是否还是不足。 大致流程&a…

redis—cluster集群

一:Redis Cluster特点 多主多从,去中心化:从节点作为备用,复制主节点,不做读写操作,不提供服务不支持处理多个key:因为数据分散在多个节点,在数据量大高并发的情况下会影响性能&…

Columns Page “列”页面

“列”页提供了列管理工具,其中包括用于添加和删除列的按钮、显示绑定数据源中字段名称的列表框以及网格列、提供对所选列属性的访问的属性网格。 Columns 页面提供 Column properties (列属性)、Column options (列选项&#xff…

Electron-(三)网页报错处理与请求监听

在前端开发中,Electron 是一个强大的框架,它允许我们使用 Web 技术构建跨平台的桌面应用程序。在开发过程中,及时处理网页报错和监听请求是非常重要的环节。本文将详细介绍 Electron 中网页报错的日志记录、webContents 的监听事件以及如何监…

如何使用JMeter进行性能测试的保姆级教程

性能测试是确保网站在用户访问高峰时保持稳定和快速响应的关键环节。作为初学者,选择合适的工具尤为重要。JMeter 是一个强大的开源性能测试工具,可以帮助我们轻松模拟多用户场景,测试网站的稳定性与性能。本教程将引导你通过一个简单的登录场…

微信小程序canvas 生成二维码图片,画图片,生成图片,将两个canvas结合并保存图片

需求实现步骤如下 先定义两个canvas一个canvas myQrcode画二维码的图片另一个canvas mycanvas画一个背景图,并把二维码画到这个canvas上,mycanvas这个canvas生成一张图片,返回图片的临时路径最后保存图片到手机 首先wxml,新版微信小程序can…

Java之继承抽象类用法实例(三十一)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【…

使用Matplotlib绘制箱线图:详细指南与示例

在数据分析和可视化领域,箱线图(Box Plot)是一种强大的工具,用于展示数据的分布特征,包括中位数、四分位数、异常值等。本文将详细介绍如何使用Matplotlib库在Python中绘制箱线图,并通过一个实际的血压数据…

从0开始linux(13)——进程(4)进程空间地址(1)

欢迎来到博主的专栏:从0开始linux 博主ID:代码小豪 文章目录 进程空间地址 还记得博主在之前介绍子进程时说过的话吗?子进程与父进程共享代码,而数据却不共享;这很好理解,因为子进程和父进程是不同的进程&a…

Java线程安全集合之COW

概述 java.util.concurrent.CopyOnWriteArrayList写时复制顺序表,一种采用写时复制技术(COW)实现的线程安全的顺序表,可代替java.util.ArrayList用于并发环境中。写时复制,在写入时,会复制顺序表的新副本&…

K8S调度不平衡问题分析过程和解决方案

不平衡问题排查 问题描述: 1、业务部署大量pod(据反馈,基本为任务型进程)过程中,k8s node内存使用率表现不均衡,范围从80%到百分之几; 2、单个node内存使用率超过95%,仍未发生pod驱逐,存在node…

Janus:开创统一的多模态理解和生成框架

Janus是DeepSeek开源的多模式自回归框架,统一了多模态理解和生成,既可以理解图片内容又可以生成图片。 1.简介 Janus 是一种新颖的自回归框架,它将多模态理解和生成统一起来。它通过将视觉编码解耦为单独的路径来解决以前方法的局限性&…