RabbitMQ学习一

RabbitMQ学习

  • RabbitMQ相关概念
  • Virtual host数据隔离
  • SpringAMQP
    • 第一种 基本消息模型
    • 第二种 WorkQueues模型
    • 第三种 发布订阅模型(fanout交换机)
      • fanout交换机实例
    • 第四种 Direct交换机
      • direct交换机实例
      • 基于注解的方式声明——direct交换机
    • 第五种Topic交换机
      • 基于注解的方式声明——Topic交换机
  • 消息转换器
  • 配置JSON转换器

RabbitMQ相关概念

在这里插入图片描述
其中包含几个概念:
1. publisher:生产者,也就是发送消息的一方
2. consumer:消费者,也就是消费消息的一方
3. queue:队列,存储消息。生产者投递的消息会暂存在消息队列中,等待消费者处理
4. exchange:交换机,负责消息路由。生产者发送的消息由交换机决定投递到哪个队列。
5. virtual host:虚拟主机,起到数据隔离的作用(相当于独立的数据库)。每个虚拟主机相互独立,有各自的exchange、queue

Virtual host数据隔离

这里的用户都是RabbitMQ的管理或运维人员。目前只有安装RabbitMQ时添加的itheima这个用户。仔细观察用户表格中的字段,如下:
在这里插入图片描述

  • Name:itheima,也就是用户名
  • Tags:administrator,说明itheima用户是超级管理员,拥有所有权限
  • Can access virtual host: /,可以访问的virtual host,这里的/是默认的virtual host

对于小型企业而言,出于成本考虑,我们通常只会搭建一套MQ集群,公司内的多个不同项目同时使用。这个时候为了避免互相干扰, 我们会利用virtual host的隔离特性,将不同项目隔离。一般会做两件事情:

  • 给每个项目创建独立的运维账号,将管理权限分离。
  • 给每个项目创建不同的virtual host,将每个项目的数据隔离。

创建用户hmall 并分配administrator权限
在这里插入图片描述
此时hmall用户是没有任何virtual host的访问权限
在这里插入图片描述
然后切切换用户hmall进行登录,并给项目创建一个单独的virtual host,进行项目之间的隔离
在这里插入图片描述
由于我们是登录hmall账户后创建的virtual host,因此回到users菜单,你会发现当前用户已经具备了对/hmall这个virtual host的访问权限了:
在这里插入图片描述
之前在virual host为/下创建的队列、交换机就看不到了。

SpringAMQP

RabbitMQ官方提供的Java客户端编码相对复杂,一般生产环境下我们更多会结合Spring来使用。而Spring的官方刚好基于RabbitMQ提供了这样一套消息收发的模板工具:SpringAMQP

  • RabbitMQ提供了6中消息模型,但是第6种RPC,并不属于MQ
  • 其实3、4、5都属于订阅模型,只不过路由的方式不同
    在这里插入图片描述

第一种 基本消息模型

其实就是生产者将消息发送到队列,消费者从队列中获取消息,队列是存储消息的缓冲区。(可以直接向队列发送消息,跳过交换机)——这种模式比较简单,很少在生产中使用。
在这里插入图片描述

第二种 WorkQueues模型

Work queues,任务模型。简单来说就是让多个消费者绑定到一个队列,共同消费队列中的消息,主要处理消息堆积,可以使用work 模型,多个消费者共同处理消息,消息处理的速度就能大大提高了。
在这里插入图片描述

  • 但WorkQueues 是平均分配给每个消费者,并没有考虑到消费者的处理能力。导致1个消费者空闲,另一个消费者忙的不可开交。没有充分利用每一个消费者的能力
  • 可以在spring中简单的配置,可以解决这个问题,我们修改consumer服务的application.yml文件,添加配置
spring:rabbitmq:listener:simple:prefetch: 1 # 每次只能获取一条消息,处理完成才能获取下一个消息

第三种 发布订阅模型(fanout交换机)

发布订阅模型,添加两个队列,分别各用一个消费者监听,设置一个交换机,类型为广播(fanout),生产者将消息发送给交换机,而交换机将消息投递给所有与本交换机绑定(routingKey)的队列中。
在这里插入图片描述
交换机只能转发消息,不能存储消息,有队列绑定就转发到队列里,没有队列时候,交换机里的消息会立马丢失。

  • 1) 可以有多个队列
  • 2) 每个队列都要绑定到Exchange(交换机)
  • 3) 生产者发送的消息,只能发送到交换机
  • 4) 交换机把消息发送给绑定过的所有队列
  • 5) 订阅队列的消费者都能拿到消息

fanout交换机实例

//发布订阅模式的配置,包括两个队列和对应的订阅者,发布者的交换机类型使用fanout(子网广播),两根网线binding用来绑定队列到交换机
@Configuration
public class FanoutExchangeConfig {@Beanpublic Queue myQueue1() {Queue queue=new Queue("queue1");return queue;}@Beanpublic Queue myQueue2() {Queue queue=new Queue("queue2");return queue;}/*** 声明交换机*/@Beanpublic FanoutExchange fanoutExchange(){FanoutExchange fanoutExchange=new FanoutExchange("fanout");return fanoutExchange;}/*** 绑定队列到交换机上*/@Beanpublic Binding binding1(){Binding binding=BindingBuilder.bind(myQueue1()).to(fanoutExchange());return binding;}/*** 绑定队列2到交换机上*/@Beanpublic Binding binding2(){Binding binding=BindingBuilder.bind(myQueue2()).to(fanoutExchange());return binding;}}

查看交换机
在这里插入图片描述
绑定到交换机下的队列
在这里插入图片描述

第四种 Direct交换机

在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。
在这里插入图片描述
在Direct模型下:

  • 队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
  • 消息的发送方在 向 Exchange发送消息时,也必须指定消息的 RoutingKey。
  • Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routingkey与消息的 Routing key完全一致,才会接收到消息

direct交换机实例

direct模式由于要绑定多个KEY,会非常麻烦,每一个Key都要编写一个binding:

//direct直连模式的交换机配置,包括一个direct交换机,两个队列,4根网线binding
@Configuration
public class DirectExchangeConfig {@Beanpublic DirectExchange directExchange(){DirectExchange directExchange=new DirectExchange("direct");return directExchange;}@Beanpublic Queue directQueue1() {Queue queue=new Queue("directqueue1");return queue;}@Beanpublic Queue directQueue2() {Queue queue=new Queue("directqueue2");return queue;}//4个binding将交换机和相应队列连起来@Beanpublic Binding bindingblack2(){Binding binding=BindingBuilder.bind(directQueue1()).to(directExchange()).with("black");return binding;}@Beanpublic Binding bindingorange(){Binding binding=BindingBuilder.bind(directQueue1()).to(directExchange()).with("orange");return binding;}@Beanpublic Binding bindingblack(){Binding binding=BindingBuilder.bind(directQueue2()).to(directExchange()).with("black");return binding;}@Beanpublic Binding bindinggreen(){Binding binding=BindingBuilder.bind(directQueue2()).to(directExchange()).with("green");return binding;}}

基于注解的方式声明——direct交换机

基于@Bean的方式声明队列和交换机比较麻烦,Spring还提供了基于注解方式来声明。

例如,我们同样声明Direct模式的交换机和队列:

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "hmall.direct", type = ExchangeTypes.DIRECT),key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}

第五种Topic交换机

Topic类型Exchange可以让队列在绑定BindingKey 的时候使用通配符!
BindingKey 一般都是有一个或多个单词组成,多个单词之间以“ .”分割,例如: item.insert

通配符规则:

  • #:匹配一个或多个词
  • *:匹配不多不少恰好1个词

举例:
item.#:能够匹配item.spu.insert 或者 item.spu
item.*:只能匹配item.spu

在这里插入图片描述

基于注解的方式声明——Topic交换机

@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),key = "china.#"
))
public void listenTopicQueue1(String msg){System.out.println("消费者1接收到topic.queue1的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),exchange = @Exchange(name = "hmall.topic", type = ExchangeTypes.TOPIC),key = "#.news"
))
public void listenTopicQueue2(String msg){System.out.println("消费者2接收到topic.queue2的消息:【" + msg + "】");
}

消息转换器

在数据传输时,它会把你发送的消息序列化为字节发送给MQ,接收消息的时候,还会把字节反序列化为Java对象。 只不过,默认情况下Spring采用的序列化方式是JDK序列化。众所周知,JDK序列化存在下列问题:

  • 数据体积过大
  • 有安全漏洞
  • 可读性差

配置JSON转换器

显然,JDK序列化方式并不合适。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。

在publisher和consumer两个服务中都引入依赖:


<dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId><version>2.9.10</version>
</dependency>
@Bean
public MessageConverter messageConverter(){// 1.定义消息转换器Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();// 2.配置自动创建消息id,用于识别不同消息,也可以在业务中基于ID判断是否是重复消息jackson2JsonMessageConverter.setCreateMessageIds(true);return jackson2JsonMessageConverter;
}

消息转换器中添加的messageId可以便于我们将来做幂等性判断。
在consumer服务中定义一个新的消费者,publisher是用什么类型发送,那么消费者也一定要用什么类型接收,格式如下:

@RabbitListener(queues = "object.queue")
public void listenSimpleQueueMessage(Map<String, Object> msg) throws InterruptedException {System.out.println("消费者接收到object.queue消息:【" + msg + "】");
}

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

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

相关文章

Spring Security 6.x 系列(7)—— 源码分析之Builder设计模式

一、Builder设计模式 WebSecurity、HttpSecurity、AuthenticationManagerBuilder 都是框架中的构建者&#xff0c;把他们放到一起看看他们的共同特点&#xff1a; 查看AuthenticationManagerBuilder的继承结构图&#xff1a; 查看HttpSecurity的继承结构图&#xff1a; 查看W…

记录 | onnx-simplifier安装、使用

安装&#xff1a; pip install onnx-simplifier# 若想加速 # [可选] 使用豆瓣源加速 pip install -i https://pypi.douban.com/simple onnx-simplifier# [可选] 使用阿里源加速 pip install -i http://mirrors.aliyun.com/pypi/simple onnx-simplifier使用&#xff1a; pytho…

vue开发中遇到的问题记录

文章目录 前言1、css 即时使用了scoped子组件依然会生效2、路由配置如果出现重复name&#xff0c;只会生效最后一个&#xff0c;且前端的路由无效3、组件之间事件传递回调需要先定义emits: []&#xff0c;不然会警告提示4、动态配置数据中引入了组件为参数&#xff0c;出现警告…

Android 断点调试

Android 调试 https://developer.android.google.cn/studio/debug?hlzh-cn 调试自己写的代码&#xff08;不在Android源码&#xff09; 点击 Attach debugger to Android process 图标 需要在添加断点界面手动输入函数名 但也可以不手动&#xff0c;有个技巧可以new 空proje…

了解SpireCV如何利用G1吊舱进行点击跟踪

功能概述 SpireCV-SDK是一个专为智能无人系统打造的边缘实时感知SDK库。该库能够控制无人机的相机和吊舱&#xff0c;包括拍照、录像、推流等功能&#xff0c;并可以保存视频和进行推流。此外&#xff0c;SpireCV-SDK还集成了目标检测、识别与跟踪功能&#xff0c;以实现更智能…

Everything结合内网穿透搭建在线资料库并实现随时随地远程访问

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前…

自己动手实现一个深度学习算法——七、卷积神经网络

文章目录 1.整体结构2.卷积层1&#xff09;全连接层存在的问题2&#xff09;卷积运算3&#xff09;填充4&#xff09;步幅5&#xff09;3维数据的卷积运算6&#xff09;结合方块思考7&#xff09;批处理 3.池化层1&#xff09;池化层的特征 4.卷积层和池化层的实现1&#xff09…

Python Scrapy分布式爬虫

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在当今信息爆炸的时代&#xff0c;获取大规模数据对于许多应用至关重要。而分布式爬虫作为一种强大的工具&#xff0c;在处理大量数据采集和高效爬取方面展现了卓越的能力。 本文将深入探讨分布式爬虫的实际应用…

Java数据结构《队列和邻接矩阵实现图的广度优先搜索》题目

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度偏难的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我写完…

redis相关题

1 什么是Redis Redis(Remote Dictionary Server) 是⼀个使⽤ C 语⾔编写的&#xff0c;开源的&#xff08;BSD许可&#xff09;⾼性能⾮关系型&#xff08;NoSQL&#xff09;的键值对数据库。Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串&#xff0c;…

C++作业3

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 代码&#xff1a; #include <iostream>using n…

Flutter页面刷新失败?看看是不是这个原因

文章目录 问题描述解决办法在控件A中定义回调函数在页面中使用控件A 原因分析回顾问题原因分析 setState使用注意事项上下文正确性异步更新避免深层嵌套避免频繁调用避免在 build 方法中调用避免在 dispose 方法中调用 问题描述 我用flutter开发了一个页面&#xff0c;页面上有…

Java SpringBoot Controller常见写法

文章目录 环境Controller调用脚本运行结果总结 环境 系统: windows 11 工具: java, idea, git bash Controller 接口常见有以下几种方式 其中&#xff1a; Tobj 调用脚本 我的是windows 系统&#xff0c;使用 git bash 窗口运行, 用 cmd 或者 power shell 会有问题 curl …

8、Qt中定时器的使用

一、说明 在Qt中常使用如下两种定时器 1、使用QObiect类的定时器事件QTimerEvent 与定时器相关的函数有&#xff1a;startTimer()、timeEvent()、killTimer()&#xff1b;startTimer(int interval)函数开始一个定时器并返回定时器ID&#xff0c;如果不能开始一个定时器&…

手把手教你Spring Security Oauth2自定义授权模式

目录 前言1、自定义认证对象2、自定义TokenGranter3、自定义AuthenticationProvider4、配置自定义AuthenticationProvider、自定义TokenGranter5、配置客户端授权模式6、测试 前言 在Oauth2中&#xff0c;提供了几种基本的认证模式&#xff0c;有密码模式、客户端模式、授权码…

传统算法:使用 Pygame 实现选择排序

使用 Pygame 模块实现了选择排序的动画演示。首先,它生成一个包含随机整数的数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过选择排序算法对数组进行排序,动画效果可视化每一步的排序过程。在排序的过程中,程序找到未排序部分的最小元素,并将其与未排序部分…

数据结构 / 队列 / 循环队列

1. 定义 为充分利用向量空间&#xff0c;克服假溢出现象的方法是&#xff1a;将向量空间想象为一个首尾相接的圆环&#xff0c;并称这种向量为循环向量。存储在其中的队列称为循环队列&#xff08;Circular Queue&#xff09;。循环队列是把顺序队列首尾相连&#xff0c;把存储…

字符集与编码规则

字符集 强调&#xff1a;UTF-8是编码规则&#xff0c;不是字符集 过程&#xff1a; 字符 --查表获得对应数字&#xff0c;--编码 解码---查表----获取字符 ASCII码 &#xff1a;一个字节 8bit GBK字符集&#xff08;windows系统默认使用的GBK,系统显示ANSI&#xff09; 存…

四、Lua循环

文章目录 一、while(循环条件)二、for&#xff08;一&#xff09;数值for&#xff08;二&#xff09;泛型for&#xff08;三&#xff09;repeat util 既然同为编程语言&#xff0c;那么控制逻辑里的循环就不能缺少&#xff0c;它可以帮助我们实现有规律的重复操作&#xff0c;而…

AIGC-文生视频

stable diffusion&#xff1a; stable diffusion原理解读通俗易懂&#xff0c;史诗级万字爆肝长文&#xff0c;喂到你嘴里 - 知乎个人网站一、前言&#xff08;可跳过&#xff09;hello&#xff0c;大家好我是 Tian-Feng&#xff0c;今天介绍一些stable diffusion的原理&#…