RabbitMQ深入 —— 交换机

news2024/11/26 14:52:23

前言

        在这篇文章中,荔枝围绕交换机梳理RabbitMQ中交换机相关知识,主要包括:扇出交换机、直接交换机、主题交换机,根据不同的交换机引出相应的RabbitMQ模式。同样的本篇文章也是主要围绕如何通过交换机定向群体发送消息这一个问题来梳理的,希望能够帮助到有需要的小伙伴~~~


文章目录

前言

一、交换机

1.1 基本概念 

1.2 交换机的类型

1.2.1 默认交换机AQMP 

1.2.2  临时队列

1.2.3 扇出交换机

1.2.4 直接交换机

二、发布订阅模式

三、Topic交换机和主题模式

总结


一、交换机

1.1 基本概念 

        在前面学习的内容中,没有涉及到有关交换机的内容,这时因为默认使用到了RabbitMQ提供的交换机。RabbitMQ消息传递模型的核心思想是:生产者生产的消息从不会直接发送到队列。生产者只需要将消息发送到交换机,由交换机来决定将消息转发到哪些消息队列中。交换机工作的内容非常简单,一方面它接收来自生产者的消息,另一方面将它们推入队列。交换机必须确切知道如何处理收到的消息,这由交换机的类型来决定。

1.2 交换机的类型

        交换机的类型总共有一下五种:默认(AMQP default)、direct(直接)、topic(主题)、headers(标题)、fanout(扇出 | 发布订阅)。

1.2.1 默认交换机AQMP 

默认交换机通常是用一个空字符串来标识的,比如在前面文章中的用法

channel.basicPublish("",queueName,null,message.getBytes());

消息能路由发送到队列中其实是由routingKey(bingingKey)绑定的Key指定的,这个routingKey起了一个类似路由分发的作用。

1.2.2  临时队列

临时队列在我们断开消费者的连接的时候队列会被自动删除。创建一个临时队列的方式比较简单:

String queueName = channel.queueDeclare().getQueue();

1.2.3 扇出交换机

扇出交换机是指交换机所连接的队列的路由关键词routingKey是一样的,因此该交换机所连接的队列可以同时获得交换机转接的来自生产者的消息。关于该交换机模式的具体实现可以看看下面(二、发布订阅模式)中的内容(建议先跳过去看)。

1.2.4 直接交换机

        直接交换机和扇出交换机相比最大的区别就是直接交换机可以根据路由关键词来实现消息的定向广播,在发送方发送的时候声明RoutingKey,交换机可以将发送过来的消息通过管道定向地输送到指定的消费者队列。下面看看这个demo:

发布者

package com.crj.rabbitmq.direct;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;

import java.util.Scanner;

public class Publish {
    //交换机的名字
    public static final String EXCHANGE_NAME = "direct";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //控制台输出消息
        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()) {
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"info",null,message.getBytes("UTF-8"));
            System.out.println("生产者发布消息:"+message);
        }
    }
}

消息接收者

package com.crj.rabbitmq.direct;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class Consumer2 {
    public static final String EXCHANGE_NAME = "direct";
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //声明一个临时队列并随机生成名字
        channel.queueDeclare("disk",false,false,false,null);

        //绑定交换机与队列
        channel.queueBind("disk",EXCHANGE_NAME,"error");
        System.out.println("Consumer正在等待接收消息。。。。。");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message)->{
            System.out.println("Consumer2控制台打印的信息:"+new String(message.getBody(),"UTF-8"));
        };
        //消费者开始消费消息
        channel.basicConsume("disk",true,deliverCallback,(consumerTag)->{});
    }
}
package com.crj.rabbitmq.direct;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class Consumer {
    public static final String EXCHANGE_NAME = "direct";
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"direct");
        //声明一个临时队列并随机生成名字
        channel.queueDeclare("console",false,false,false,null);
        //绑定交换机与队列
        channel.queueBind("console",EXCHANGE_NAME,"info");
        //多重绑定
        channel.queueBind("console",EXCHANGE_NAME,"warning");
        System.out.println("Consumer正在等待接收消息。。。。。");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message)->{
            System.out.println("Consumer控制台打印的信息:"+new String(message.getBody(),"UTF-8"));
        };
        //消费者开始消费消息
        channel.basicConsume("console",true,deliverCallback,(consumerTag)->{});
    }
}

多重绑定:也就是消费者可以一次性绑定多个信道队列来接收来自不同交换机发送过来的消息。


二、发布订阅模式

发布订阅模式比较容易理解,其实就是交换机会根据RoutingKey将目标消息广播到相应的队列中。与之前文章不同在于,在这里我们定义了交换机的名字EXCHANGE_NAME,并通过Channel对象的exchangeDeclare方法来实现交换机模式的设置。

消息发布者:

区别于之前,这里我们需要在basicPublish为当前信道队列设置好交换机的名字以及相应的路由关键词,同时传入message内容。

package com.crj.rabbitmq.PublishAndOrder;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;

import java.util.Scanner;

public class Publish {
    public static final String EXCHANGE_NAME = "LOGS";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //控制台输出消息
        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()) {
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"routingKey路由关键词",null,message.getBytes("UTF-8"));
            System.out.println("生产者发布消息:"+message);
        }
    }
}

消息接收者

由于消息接收者的队列在接收完消息之后可以丢弃,因此我们可以随机生成队列名并开启自动清除,通过Channel对象的queueBind方法将交换机和队列进行绑定,之后就可以开始消费消息了。

package com.crj.rabbitmq.PublishAndOrder;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

public class Receiver {
    //交换机的名称
    public static final String EXCHANGE_NAME = "LOGS";
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个临时队列并随机生成名字
        String queueName = channel.queueDeclare().getQueue();

        //绑定交换机与队列
        channel.queueBind(queueName,EXCHANGE_NAME,"routingKey路由关键词");
        System.out.println("等待接收消息。。。。。");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag,message)->{
            System.out.println("控制台打印的信息:"+new String(message.getBody(),"UTF-8"));
        };
        //消费者开始消费消息
        channel.basicConsume(queueName,true,deliverCallback,(consumerTag)->{});

    }
}

运行结果: 

可以看到两个信道队列的消费者是同时获得生产者发送的消息的,这就是扇出交换机,也是发布确认模式。 


三、Topic交换机和主题模式

        在前面的扇出交换机和直接交换机分别实现了两种比较极端的模式:扇出是广播,不管对象是谁;直接交换机是指定定向的对象进行消息的发送,而不能同时发送消息给多个对象。为了实现将消息广播给指定的对象这一功能,我们引入了Topic交换机。在Topic交换机中,发送的类型是topic交换机的消息的routing_key不能随意写,必须满足一定的规范:它必须是一个单词列表,以点号分隔开。这些单词可以是任意单词,说:"stock.usd.nyse","nyse.vmw","quck.orange.rabbit".这种类型的。当然这个单词列表最多不能超过255个字节。

在这个规则列表中,其中有两个替换符是需要注意的:

  • *(星号)可以代替一个单词
  • #(井号)可以替代零个或多个单词

在发送方和消息的接收方们之间可以执行一个约定,定义各自发布的消息的格式,这样就可以实现在指定消息接收群体对象中进行广播了。

下面我们可以看看demo示例:

生产者

生产者中我们定义了一个map结构来构造消息集合,并将map中的消息单独发出,map对象中记录了相应的routingKey和消息体。 

package com.crj.rabbitmq.topic;

import com.crj.rabbitmq.utils.RabbitMqUtil;
import com.rabbitmq.client.Channel;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Publish {
    //交换机的名字
    public static final String EXCHANGE_NAME = "topic";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtil.getChannel();
        //创建消息集合
        Map<String,String> bindingKeyMap = new HashMap<>();
        bindingKeyMap.put("quick.orange.rabbit","被队列QlQ2接收到");
        bindingKeyMap.put("1azy.orange.elephant","被队列Q1Q2接收到");
        bindingKeyMap.put("quick.orange.fox","被队列Ql接收到");
        bindingKeyMap.put("lazy.brown.fox","被队列Q2接收到");
        bindingKeyMap.put("lazy.pink.rabbit","虽然满足两个绑定但只被队列Q2接收一次");
        bindingKeyMap.put("quick.brown..fox","不匹配任何绑定不会被任何队列接收到会被丢弃");
        bindingKeyMap.put("quick.orange.male.rabbit","是四个单词不匹配任何绑定会被丢弃");
        bindingKeyMap.put("lazy.orange.male.rabbit","是四个单词但匹配Q2");

        for (Map.Entry<String, String> bindingKeyEntry : bindingKeyMap.entrySet()) {
            String routingKey = bindingKeyEntry.getKey();
            String message = bindingKeyEntry.getValue();
            channel.basicPublish(EXCHANGE_NAME,routingKey,null,message.getBytes());
            System.out.println("发出消息:"+message);
        }
    }
}

消费者

两个消费者分别定义不同的routingKey规则, 

 


总结

        通过上面的学习中,我们对消息发送者和消息接收者二者的功能代码模块都比较熟悉了,同样也已经学习了五种核心模式了——简单、工作、发布确认、发布订阅、主题。虽然文章内容简单但还是值得作为笔记回顾的哈哈哈哈~~~

今朝已然成为过去,明日依然向往未来!我是荔枝,在技术成长之路上与您相伴~~~

如果博文对您有帮助的话,可以给荔枝一键三连嘿,您的支持和鼓励是荔枝最大的动力!

如果博文内容有误,也欢迎各位大佬在下方评论区批评指正!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

澳洲硕士申请QA

Q&A 申请一般问题 澳洲申请时间 澳洲分2月跟7月开学&#xff0c;不分rolling。随时申请&#xff0c;截止日期前申请就行&#xff0c;&#xff08;具体时间官网有写&#xff09; 研究生学位时长 它整体的要求一般就是如果说你要申请的这个专业是本专业&#xff0c;那他…

分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测

分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测 目录 分类预测 | Matlab实现基于MIC-BP-Adaboost最大互信息系数数据特征选择算法结合Adaboost-BP神经网络的数据分类预测效果一览基本介绍研究内容程序设计参考…

Linux内核中断机制

什么是中断&#xff1f; 中断是一种打断程序的正常执行流程的事件&#xff0c;这种事件以电信号的形式出现&#xff0c;可以由硬件设备或者CPU本身生成。 在中断发生后&#xff0c;正常的执行流被立即中止&#xff0c;转而执行中断处理程序(handler)。中断处理完成之后&#…

IT运维:使用数据分析平台监控Windows Eventlog

TIPS&#xff1a;本文鸿鹄版本&#xff1a;2.10.0及以上版本 概述 本文基于《IT运维&#xff1a;利用鸿鹄采集Windows event log数据》&#xff08;以下简称原文&#xff09;文章进行了细化与延伸。主要包括细化了安装步骤&#xff0c;增加了仪表板。 鸿鹄端配置 创建数据集与数…

[Linux入门]---搭建Linux环境

1.Linux环境的搭建方式 使用Linux操作系统的三种途径&#xff1a; 1.直接安装在物理机上&#xff0c;但是由于 Linux 桌面使用起来非常不友好&#xff0c;不推荐。 2.使用虚拟机软件&#xff0c;将 Linux 搭建在虚拟机上&#xff0c;但是由于当前的虚拟机软件(如 VMWare 之类的…

科研生产力:Zotero

目录 Zotero安装配置Zotero常用插件1. Zotero Connector2. Jasminum-茉莉花插件3. Zotero-scihub4. Zotero-pdf-translate5. Zotero-if6. Zotero-style7. Zotero-tag8. ZotFile9. zotero-better-notesZotero GPT 一些学习资源 Zotero安装配置 进入Zotero官网&#xff1a;https:…

前端用户体验设计:创造卓越的用户界面和交互

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 用户体验&#xff08;Us…

Softek Barcode Reader Toolkit 9.3 Crack

现在使用 Pdfium 读取 PDF 文件并改进了对 QRCode、PDF417 和 Code 39 的支持。 2023 年 9 月 11 日 - 16:32新版本 特征 现在使用 Pdfium 读取 PDF 文件。 提高了 GetBarStringPos 返回值的准确性。 如果 PDF417 条形码包含超过数据字节计数的符号长度描述符&#xff0c;则它会…

透视俄乌网络战之二:Conti勒索软件集团(下)

透视俄乌网络战之一&#xff1a;数据擦除软件 透视俄乌网络战之二&#xff1a;Conti勒索软件集团&#xff08;上&#xff09; Conti勒索软件集团&#xff08;下&#xff09; 1. 管理面板源代码2. Pony凭证窃取恶意软件3. TTPs4. Conti Locker v2源代码5. Conti团伙培训材料6. T…

SAP 信息类型:使用 PA30,PA20 创建,更改,复制,删除,概览

目录 创建信息类型 显示信息类型 更改信息类型 复制信息类型 删除信息类型 显示信息类型概述 创建信息类型 步骤 1&#xff09;在 SAP 命令提示符下&#xff0c;输入事务 PA30 步骤 2&#xff09;在下一个 SAP 屏幕中&#xff0c; 输入人员编号点击输入按钮 选择相关的…

SaaS软件能保证数据安全吗?

SaaS软件能保证数据安全吗&#xff1f; 本文将要尝试从各个方面尽可能客观的去阐述这个问题&#xff0c;而不是简单自嗨式的说简道云平台如何保障数据安全。 建议先收藏起来慢慢品&#xff01; 01 SaaS安全到底是什么&#xff1f;——定义解读 本文所用SaaS平台>>>…

VR航天航空巡展VR科技馆航天主题科普设备沉浸遨游太空

每当飞机飞过头顶&#xff0c;我们总是忍不住抬头去仰望。从嫦娥奔月的神话传说&#xff0c;到莱特兄弟实现了上天翱翔的梦想&#xff0c;人类一直在不断探索更辽阔的天空和浩瀚的宇宙。 航空科普 寻梦而行 普乐蛙VR航天航空巡展&#xff0c;正在湖南郴州如火如荼的进行中&…

el-dialog窗口添加滚动条

0 效果 1 代码 /deep/.addMicroDialog {height: 700px !important;overflow-y: scroll;}/deep/.addMicroDialog:hover::-webkit-scrollbar-thumb {background: #9cbaff;border-radius: 10px;}/deep/.addMicroDialog::-webkit-scrollbar {width: 6px;height: 0px;}

R--基础知识总结

R程序包的安装和加载 install.packageS(TSA) library(TSA) R向量 (vector) 数值向量 1.赋值 x<-c(1,2,3,4)assign( x,c(1,2,3,4))xc(1,2,3,4)x<-2*1:15 % x(2,4,...,30) 等差运算优先于乘法运算seq(fromvalue1,tovalue2,byvalue3) seq(length…

golang iris框架 + linux后端运行

go mod init myappgo get github.com/kataras/iris/v12latestpackage mainimport "github.com/kataras/iris/v12"func main(){app : iris.New()app.Listen(":port") }打包应用 go build main.go开启服务 #nohup ./程序名称 nohup ./main关闭后台 #ps -e…

国际版阿里云/腾讯云免费:阿里云产品-弹性核算简介(依据官网转载)

阿里云产品-弹性核算简介(依据官网转载) 云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云供给的功能杰出、安稳牢靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;等级云核算服务。 实例&#xff1a;等同于一台虚拟服务器&#xf…

vscode如何设置文件折叠

随着项目的不断迭代开发&#xff0c;复杂度越来越高&#xff0c;配置文件越来越多&#xff0c;导致vscode左侧文件列表展示非常不直观&#xff0c;幸好可以通过文件折叠来简化展示效果&#xff0c;把同类相关的文件折叠在一块展示&#xff0c;方便查看配置文件。配置好后的效果…

C++之vector迭代器函数begin、end、rebegin、rend、cbegin、cend、crbegin、crend总结(二百零一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

视频监控管理平台/视频汇聚/视频云存储EasyCVR安全检查的相关问题及解决方法3.0

智能视频监控系统/视频云存储/集中存储/视频汇聚平台EasyCVR具备视频融合汇聚能力&#xff0c;作为安防视频监控综合管理平台&#xff0c;它支持多协议接入、多格式视频流分发&#xff0c;视频监控综合管理平台EasyCVR支持海量视频汇聚管理&#xff0c;可应用在多样化的场景上&…

Weblogic SSRF漏洞

Weblogic SSRF漏洞 1.环境搭建 http://10.9.75.198:7001/uddiexplorer/2.漏洞复现 SSRF漏洞存在于http://10.9.75.198:7001/uddiexplorer/SearchPublicRegistries.jsp2.1bp抓包&#xff0c;测试该漏洞。通过测试端口&#xff0c;查看哪个端口能够进行具体得操作 可访问的端…