RabbitMQ学习05

news2024/11/23 15:07:30

文章目录

    • 交换机
      • 1.Exchanges
        • 1.1 概念
        • 1.2 类型
        • 1.3 无名exchange
      • 2. 临时队列
      • 3. 绑定(bings)
      • 4. Fanout
        • 4.1 介绍
      • 5.Direct exchange
        • 5.1 介绍
        • 5.2 多重绑定
        • 5.3 实战:
      • 6. Topics
        • 6.1 规则
        • 6.2 实战

交换机

1.Exchanges

1.1 概念

    RabbitMQ 消息传递模型的核心思想是: 生产者生产的消息从不会直接发送到队列。实际上,通常生产者甚至都不知道这些消息传递传递到了哪些队列中。
    相反,生产者只能将消息发送到交换机(exchange),交换机工作的内容非常简单,一方面它接收来自生产者的消息,另一方面将它们推入队列。交换机必须确切知道如何处理收到的消息。是应该把这些消息放到特定队列还是说把他们到许多队列中还是说应该丢弃它们。这就的由交换机的类型来决定。
在这里插入图片描述

1.2 类型
  1. 直接(direct)
  2. 主题(topic)
  3. 标题(header)
  4. 扇出(fanout)
1.3 无名exchange

    第一个参数是交换机的名称。空字符串表示默认或无名称交换机:消息能路由发送到队列中其实是由 routingKey(bindingkey)绑定 key 指定的,如果它存在的话

2. 临时队列

    队列的名称我们来说至关重要-我们需要指定我们的消费者去消费哪个队列的消息。
每当我们连接到 Rabbit 时,我们都需要一个全新的空队列,为此我们可以创建一个具有随机名称的队列,或者能让服务器为我们选择一个随机队列名称那就更好了。其次一旦我们断开了消费者的连接,队列将被自动删除
创建临时队列的方式如下:

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

3. 绑定(bings)

    binding 其实是 exchange 和 queue 之间的桥梁,它告诉我们 exchange 和那个队列进行了绑定关系。比如说下面这张图告诉我们的就是 X 与 Q1 和 Q2 进行了绑定。在这里插入图片描述

4. Fanout

4.1 介绍

    Fanout 这种类型非常简单。正如从名称中猜到的那样,它是将接收到的所有消息广播到它知道的所有队列中。系统中默认有些 exchange 类型
在这里插入图片描述

在这里插入图片描述
ReceiveLogs01 将接收到的消息打印在控制台

public class ReceiveLogs01 {
    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {

        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个队列 临时队列
        /**
         * 生成一个临时队列,队列的名称是随机的
         * 当消费者断开与队列的连接时 队列就会自动删除
         */
        String queueName = channel.queueDeclare().getQueue();
        /**
         * 绑定交换机与队列
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("等待接收消息,把接受的消息打印在屏幕上.......");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) ->{
            System.out.println("ReceiveLogs01控制台打印接受的消息:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
    }
}

ReceiveLogs02 将接收到的消息打印在控制台

public class ReceiveLogs02 {

    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {

        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");
        //声明一个队列 临时队列
        /**
         * 生成一个临时队列,队列的名称是随机的
         * 当消费者断开与队列的连接时 队列就会自动删除
         */
        String queueName = channel.queueDeclare().getQueue();
        /**
         * 绑定交换机与队列
         */
        channel.queueBind(queueName,EXCHANGE_NAME,"");
        System.out.println("等待接收消息,把接受的消息打印在屏幕上.......");

        //接收消息
        DeliverCallback deliverCallback = (consumerTag,message) ->{
            System.out.println("ReceiveLogs02控制台打印接受的消息:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});
    }
}

EmitLog 发送消息给两个消费者接收

public class EmitLog {
    //交换机名称
    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME,"fanout");

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"",null,message.getBytes(StandardCharsets.UTF_8));
            System.out.println("生产者发出消息:" + message);
        }
    }
}

5.Direct exchange

5.1 介绍

    上一节中的我们的日志系统将所有消息广播给所有消费者,对此我们想做一些改变,例如我们希望将日志消息写入磁盘的程序仅接收严重错误(errros),而不存储哪些警告(warning)或信息(info)日志消息避免浪费磁盘空间。Fanout 这种交换类型并不能给我们带来很大的灵活性-它只能进行无意识的广播,在这里我们将使用 direct 这种类型来进行替换,这种类型的工作方式是,消息只去到它绑定的routingKey 队列中去
在这里插入图片描述
    在上面这张图中,我们可以看到 X 绑定了两个队列,绑定类型是 direct。队列 Q1 绑定键为 orange,队列 Q2 绑定键有两个:一个绑定键为 black,另一个绑定键为 green.
在这种绑定情况下,生产者发布消息到 exchange 上,绑定键为 orange 的消息会被发布到队列Q1。绑定键为 blackgreen 和的消息会被发布到队列 Q2,其他消息类型的消息将被丢弃。

5.2 多重绑定

在这里插入图片描述
    当然如果 exchange 的绑定类型是 direct,但是它绑定的多个队列的 key 如果都相同,在这种情况下虽然绑定类型是 direct 但是它表现的就和 fanout 有点类似了,就跟广播差不多,如上图所示。

5.3 实战:
public class ReceiveLogsDirect01 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //声明一个队列
        channel.queueDeclare("console", false,false,false,null);

        channel.queueBind("console",EXCHANGE_NAME,"info");
        channel.queueBind("console",EXCHANGE_NAME,"warning");

        DeliverCallback deliverCallback = (consumerTag, message) ->{
            System.out.println("ReceiveLogsDirect01:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        channel.basicConsume("console",true,deliverCallback,consumerTag -> {});


    }

}
public class ReceiveLogsDirect02 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);
        //声明一个队列
        channel.queueDeclare("disk", false,false,false,null);

        channel.queueBind("disk",EXCHANGE_NAME,"error");

        DeliverCallback deliverCallback = (consumerTag, message) ->{
            System.out.println("ReceiveLogsDirect02:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        channel.basicConsume("disk",true,deliverCallback,consumerTag -> {});


    }

}
public class DirectLogs {
    //交换机名称
    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME,"error",null,message.getBytes(StandardCharsets.UTF_8));
            System.out.println("生产者发出消息:" + message);
        }
    }
}

测试结果:
    routingkey指定给哪个交换机,

6. Topics

6.1 规则

    发送到类型是 topic 交换机的消息的 routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开。这些单词可以是任意单词,比如说:“stock.usd.nyse”, “nyse.vmw”, “quick.orange.rabbit”.这种类型的。当然这个单词列表最多不能超过 255 个字节。
    在这个规则中,有两个替换符需要注意
*(星号)可以代替一个单词
#(井号)可以替代零个或多个单词
    当队列绑定关系是下列这种情况时需要引起注意:
当一个队列绑定键是#,那么这个队列将接收所有数据,就有点像 fanout 了
如果队列绑定键当中没有#和*出现,那么该队列绑定类型就是 direct 了
=

6.2 实战
public class EmitLogTopic {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception{

        Channel channel = RabbitMQUtils.getChannel();

        Map<String,String> bingKeyMap = new HashMap<>();
        bingKeyMap.put("quick.orange.rabbit","被队列 Q1Q2 接收到");
        bingKeyMap.put("azy.orange.elephant","被队列 Q1Q2 接收到");
        bingKeyMap.put("quick.orange.fox","被队列 Q1 接收到");
        bingKeyMap.put("lazy.brown.fox","被队列 Q2 接收到");
        bingKeyMap.put("azy.pink.rabbit","虽然满足两个绑定但只被队列 Q2 接收一次");
        bingKeyMap.put("quick.brown.fox","不匹配任何绑定不会被任何队列接收到会被丢弃");
        bingKeyMap.put("quick.orange.male.rabbit","是四个单词不匹配任何绑定会被丢弃");
        bingKeyMap.put("lazy.orange.male.rabbit","是四个单词但匹配 Q2");

        bingKeyMap.forEach((k,v) -> {
            try {
                channel.basicPublish(EXCHANGE_NAME,k,null,v.getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });


    }

}
public class ReceiveLogsTopic01 {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {

        Channel channel = RabbitMQUtils.getChannel();

        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //声明一个队列
        String queueName = "Q1";
        channel.queueDeclare(queueName,false,false,false,null);
        channel.queueBind(queueName,EXCHANGE_NAME,"*.orange.*");
        System.out.println("等待接收消息");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) ->{
            System.out.println("ReceiveLogsTopic01:" + new String(message.getBody(), StandardCharsets.UTF_8));
            System.out.println("接收消息:" + queueName + "绑定键:" + message.getEnvelope().getRoutingKey());
        };

        channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});


    }

}

public class ReceiveLogsTopic02 {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {

        Channel channel = RabbitMQUtils.getChannel();

        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        //声明一个队列
        String queueName = "Q2";
        channel.queueDeclare(queueName,false,false,false,null);
        channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
        channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");
        System.out.println("等待接收消息");
        //接收消息
        DeliverCallback deliverCallback = (consumerTag, message) ->{
            System.out.println("ReceiveLogsTopic01:" + new String(message.getBody(), StandardCharsets.UTF_8));
            System.out.println("接收消息:" + queueName + "绑定键:" + message.getEnvelope().getRoutingKey());
        };

        channel.basicConsume(queueName,true,deliverCallback,consumerTag -> {});


    }

}

在这里插入图片描述
测试结果:

规则结果
quick.orange.rabbit被队列 Q1Q2 接收到
lazy.orange.elephant被队列 Q1Q2 接收到
quick.orange.fox被队列 Q1 接收到
lazy.brown.fox被队列 Q2 接收到
lazy.pink.rabbit虽然满足两个绑定但只被队列 Q2 接收一次
quick.brown.fox不匹配任何绑定不会被任何队列接收到会被丢弃
quick.orange.male.rabbit是四个单词不匹配任何绑定会被丢弃
lazy.orange.male.rabbit是四个单词但匹配 Q2

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

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

相关文章

C++初阶2

目录 一&#xff0c;auto关键字 1-1&#xff0c;auto的使用 1-2&#xff0c;基于范围auto的for循环 二&#xff0c;nullptr的运用 三&#xff0c;C类的初步学习 3-1&#xff0c;类的引用 3-2&#xff0c;类的访问权限 3-3&#xff0c;类的使用 1&#xff0c;类中函数的…

SA实战 ·《SpringCloud Alibaba实战》第12章-服务网关:网关概述与核心架构

作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 大家好,我是冰河~~ 一不小心《SpringCloud Alibaba实战》专栏都更新到第12章了,再不上车就跟不上了,小伙伴们快跟上啊! 在《SpringClou…

基于AliO Things和阿里云的智能环境监控系统。

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、实习内容二、实习方法2.1搭建开发环境并完成编译2.1.1 正常完成编译的标志2.1.2 编写实例烧录程序&#xff0c;并完成烧录 2.2按键实现流水灯2.2.1 HaaS ED…

General Expression In Oral English

1. With all Due Respect 恕我直言&#xff0c; 那些和你混在一起的混蛋们只关心政治 With all due respect , these sons of bitches that youre mingling with(与.. 交际) only care about politics

A. Doremy‘s Paint 3(规律)

Problem - A - Codeforces 解析&#xff1a; 首先最多只能存在两个值&#xff0c;因为间隔必须相同。并且两个值的数量相差小于等于1 #include<bits/stdc.h> using namespace std; #define int long long const int N2e55; int t,n,a[N]; map<int,int>mp; signed…

【SpringSecurity】快速入门—通俗易懂

目录 1.导入依赖 2.继承WebSecurityConfigurerAdapter 3.实现UserDetailsService 4.记住我 5.用户注销 6.CSRF理解 7.注解功能 7.1Secured 7.2PreAuthorized 7.3PostAuthorized 7.4PostFilter 7.5ZPreFilter 8.原理解析 1.导入依赖 首先&#xff0c;在pom.xml文…

第五章 I/O管理 二、I/O控制器

目录 一、电子部件 1、I/O控制器 1.功能&#xff1a; &#xff08;1&#xff09;接受和识别CPU发出的命令&#xff1a; &#xff08;2&#xff09;向CPU报告设备的状态 &#xff08;3&#xff09;数据交换 &#xff08;4&#xff09;地址识别 2.组成 二、内存映像和寄…

磁盘调度算法之先来先服务(FCFS),最短寻找时间优先(SSTF),扫描算法(SCAN,电梯算法),LOOK调度算法

目录 1.一次磁盘读/写操作需要的时间1.寻找时间2.延迟时间3.传输时间4.影响读写操作的因素 2.磁盘调度算法1.先来先服务(FCFS)1.例题2.优缺点 2.最短寻找时间优先(SSTF)1.例题2.优缺点3.饥饿的原因 3.扫描算法(SCAN)1.例题2.优缺点 4.LOOK调度算法1.例题2.优点 5.循环扫描算法(…

81 分割回文串

分割回文串 题解1 回溯题解2 回溯dp利用dp相当于先判断哪段是回文(省掉了每次都需要调用的isValid)【预处理】 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使 每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字…

【idea】新建Maven文件都会默认在C盘下载的解决方法

Customize——>All settings 完成配置 同理&#xff0c;其他需要全局配置的设置步骤也是一样的。

第9天:字符编码

字符编码 字符串类型、文本文件的内容都是由字符组成的&#xff0c;但凡涉及到字符的存取&#xff0c;都需要考虑字符编码的问题。 存储原理&#xff1a; 1、软件运行前&#xff0c;软件的代码及其相关数据都是存放于硬盘中的 2、任何软件的启动都是将数据从硬盘中读入内存&…

JAVA-JVM 之Class字节码文件的组成 【上篇】

字节码 前言概述基本结构魔数头版本号常量池访问标志 主页传送门&#xff1a;&#x1f4c0; 传送 前言 java的特点是跨平台性&#xff0c;而跨平台的运行标准是Class字节码文件&#xff0c;Class字节码是提供平台无关性的基础模型&#xff0c;使我们无须考虑如何兼容异构系统&…

车载电子电器架构 —— 基于AP定义车载HPC

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

提升演讲与口才的三种方法

演讲和口才是在现代社会中非常重要的技能。无论是在职场中进行演讲&#xff0c;还是在日常生活中与他人进行交流&#xff0c;具备良好的演讲和口才能力都能给人带来诸多优势。然而&#xff0c;要提升自己的演讲和口才能力并不是一件容易的事情。在本文中&#xff0c;我将介绍三…

【机器学习】决策树与分类案例分析

决策树与分类案例分析 文章目录 决策树与分类案例分析1. 认识决策树2. 分类3. 决策树的划分依据4. 决策树API5. 案例&#xff1a;鸢尾花分类6. 决策树可视化7. 总结 1. 认识决策树 决策树思想的来源非常朴素&#xff0c;程序设计中的条件分支结构就是if-else结构&#xff0c;最…

pre-existing shared memory block

发生原因: 1.服务器cpu、内存进行扩容 2.非正常关闭,导致任在占用共享内存段 解决方案: 根据shmid进行关闭 ipcs -mipcrm -m xxx

进程替换..

1、单进程版 – 最简单的先看看程序替换 现象就是 1、我们用自己的进程封装了内置指令ls,并且代码中execl 后 printf 的after并没有打印出来。 2、谈进程替换的原理 单进程替换基本原理 上面例子中execl的做法非常简单粗暴&#xff0c;要调用ls&#xff0c;那么就把mycom…

使用Python,mediapipe构建手部姿势探测器

使用Python&#xff0c;mediapipe构建手部姿势探测器 1. 效果图2. 手部标志3. 源码参考 这篇博客将介绍手部标志是什么&#xff0c;以及如何使用Python&#xff0c;mediapipe构建手部姿势探测器&#xff0c; Mediapipe是一个跨平台的库&#xff0c;由谷歌开发&#xff0c;为计…

【pandas技巧】group by+agg+transform函数

目录 1. group by单个字段单个聚合 2. group by单个字段多个聚合 3. group by多个字段单个聚合 4. group by多个字段多个聚合 5. transform函数 studentsgradesexscoremoney0小狗小学部female958441小猫小学部male938362小鸭初中部male838543小兔小学部female909314小花小…

KubeSphere 社区双周报 | KubeKey 支持 Web UI | 2023.10.13-10.26

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者&#xff0c;并对近期重要的 PR 进行解析&#xff0c;同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为&#xff1a;2023.10.13-2023.…