微服务学习|初识MQ、RabbitMQ快速入门、SpringAMQP
初识MQ
同步通讯和异步通讯
同步通讯是实时性质的,就好像你用手机与朋友打视频电话,但是,别人再想与你视频就不行了,异步通讯不要求实时性,就好像你用手机发短信,好多人都能同时给你发短信,你都可以收到,而且不用及时回复。
同步调用的问题
微服务间基于Feign的调用就属于同步方式,存在一些问题
比如用户调用支付服务时,它需要先后调用订单服务、仓储服务、短信服务等,都调用结束后,支付服务再返回用户相关信息,故这个过程的响应时间实际上就是所有这些相关服务执行之后所用时间之和,这样是非常影响效率的。但是也有优点,时效性较强,可以立即得到结果
同步调用存在的问题
1.如果我们想对支付服务增加一些功能,增加一些别的服务,为了让支付功能调用这个新服务,我们需要改动相关的代码
2.调用者需要等待服务提供者响应,如果调用链过长则响应时间等于每次调用的时间之和。就如支付服务必须要等订单服务、仓储服务、短信服务都执行后,才能给出响应,很慢。
3.上述支付服务在等待其余服务响应的时候,资源是不释放的,一直在等待,高并发场景下嫉妒浪费系统资源
4.如果其中一个服务出现问题,例如仓储服务出现问题,则整个响应就无法进行了,就整个崩掉了。
异步调用方案
异步调用常见实现就是事件驱动模式
比如用户发起支付服务,此时会将该消息发给Broker,然后就不用管后面了,支付服务直接给用户响应,不需要管订单、仓储、短信这些服务的执行了,这几个服务提前订阅了这个Broker,所以,支付服务消息来了,会从Broker中获取到消息,然后执行自己的逻辑就好。
优势一:服务解耦
当我们对支付服务增加一些新的功能,新服务时,只需要将该服务订阅这个Broker即可,不需要改动支付服务的代码
优势二:性能提升,吞吐量提高
因为是异步调用,支付服务不需要关注其相关的其他服务执行,只需将支付消息发给Broker即可,然后就能直接给用户响应,非常快,后续相关的服务只需要从Broker中收到该消息后执行相关的业务操作就可。
优势三:服务没有强依赖,不担心级联失败问题
其中一个服务发生故障,整个支付服务不会因为这个服务故障了而停掉,支付服务依然会直接给用户响应。
优势四:流量削峰
因为有Broker的缘故,如果并发量比较大,这些消息都会暂存在Broker中,慢慢的让其余各服务去处理,所以能够很好的将流量削峰。
异步通信的缺点
依赖于Broker的可靠性、安全性、吞吐能力
架构复杂了,业务没有明显的流程线,不好追踪管理
什么是MQ?
MQ(MessageQueue),中文是消息队列,字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。简单来讲,Kafka对并发场景性能更高,但是没有RabbitMQ安全,所以一般情况下就用RabbitMQ就可,中规中矩。
RabbitMQ快速入门
单机部署
我们在Centos7虚拟机中使用Docker来安装。
方式一:在线拉取
方式二:从本地加载
在课前资料已经提供了镜像包
上传到虚拟机中后,使用命令加载镜像即可
安装MQ
执行下面的命令来运行MQ容器
这里第一个15672端口是用来登录RabbitMQ控制台的,第二个5672端口是用来进行异步调用的。这里也要设置RabbitMQ控制台的登录账号itcast密码123321
用宿主机ip+第一个端口15672来访问RabbitMQ控制台,账号itcast密码123321,登录即可
RabbitMQ的结构和概念
RabbitMQ中的几个概念
channel:操作MQ的工具
exchange:路由消息到队列中
queue:缓存消息
virtualhost: 虚拟主机,是对queue、exchange等资源的逻辑分组
常见消息模型
MQ的官方文档中给出了5个MQ的Demo示例,对应了几种不同的用法
HelloWorld案例
官方的Helloworld是基于最基础的消息队列模型来实现的,只包括三个角色:
publisher:消息发布者,将消息发送到队列queue
queue:消息队列,负责接受并缓存消息
consumer:订阅队列,处理队列中的消息
编写publisher消息发布者代码,新建一个连接工厂,配置本机RabbitMQ的异步调用端口,以及账号密码,然后建立一个连接,connection对象。
连接对象connection生成后,我们可以在RabbitMQ的控制台,看到了这个新生成的连接
然后用这个connection连接对象创建一个通道channel对象
执行完后,控制台也能够看到这个新建的通道
然后用channel对象新建一个名为simple.queue的队列,并给这个队列发消息
可以在控制台看到这个新创建的名为simple.queue的队列,并且队列中已经有了我们刚发送的消息
订阅该队列的consumer编写,前三步与publisher一致
最后一步变成了利用channel将消费者与队列绑定,在handleDelivery()中定义consumer的消费行为
SpringAMQP
什么是SpringAMQP
案例:利用SpringAMQP实现HelloWorld中的基础消息队列功能
流程如下:
1.在父工程中引入spring-amqp的依赖
2.在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列
3.在consumer服务中编写消费逻辑,绑定simple.queue这个队列
步骤1: 引入AMQP依赖
因为publisher和consumer服务都需要amqp依赖,因此这里把依赖直接放到父工程mq-demo中
步骤2: 在publisher中编写测试方法,向simple.queue发送消息
1.在publisher服务中编写application.yml,添加mq连接信息
2.在publisher服务中新建一个测试类,编写测试方法
运行后,可在RabbitMQ控制台看到该队列,以及队列中有消息了
什么是AMQP?
应用间消息通信的一种协议,与语言和平台无关。
SpringAMOP如何发送消息?
引入amqp的starter依赖
配置RabbitMo地址
利用RabbitTemplate的convertAndSend方法
步骤3: 在consumer中编写消费逻辑,监听simple.queue
1.在consumer服务中编写application.yml,添加mq连接信息
2.在consumer服务中新建一个类,编写消费逻辑
SpringAMQP如何接收消息?
引入amqp的starter依赖
配置RabbitMQ地址
定义类,添加@Component注解
类中声明方法,添加@RabbitListener注解,方法参数就是消息
注意:消息一旦消费就会从队列删除,RabbitMQ没有消息回溯功能
Work Queue 工作队列
Work queue,工作队列,可以提高消息处理速度,避免队列消息堆积,也就是两个消费者同时订阅一个队列,共同处理队列中的消息
案例:模拟WorkQueue,实现一个队列绑定多个消费者
基本思路如下
1.在publisher服务中定义测试方法,每秒产生50条消息,发送到simple.queue
2.在consumer服务中定义两个消息监听者,都监听simple.queue队列
3.消费者1每秒处理50条消息,消费者2每秒处理10条消息
publisher服务中定义测试方法,每20ms发送一个消息,发送50次,也就是1秒向消息队列中发送50条消息
定义两个消息监听者,都监听simple.queue队列,消费者1一秒钟能处理50条消息,消费者2一秒钟能处理5条消息,故理论上这两个消费者能在1秒内处理完publisher发送的所有(50条)消息
但是,运行起来发现,并不是按照能力强的处理的消息多这样来分配的,而是这两个监听者,各分到了一般的消息,消费者1处理偶数号的消息,消费者2处理奇数的消息,这样最终结果就是消费者1很快的处理完了总共消息的一半,25条消息,而消费者2却花了好多秒去处理分给自己25条消息,最终的结果就是这两个消费者不能够在1秒内处理完所有消息。
实际上,它是有一个预取机制造成的这样结果,进入到消息队列中的消息会被提前预取给消费者,默认的是一人一个,这样平均分配的,消费者还没处理完,但是消息都已经全部预取出来给了对应消费者,我们可以配置预取机制,让每个消费者预取消息的数量为1,每次只能获取一消息,处理完成才能获取下一个消息,这样就可以做到能者多劳的结果。
消费预取限制
修改application.yml文件,设置preFetch这个值,可以控制预取消息的上限
配置完后再启动,就发现了消费者1执行的消息要比消费者2执行的消息多了,而不是简单的将消息都平均分配给监听的两个消费者。
Work模型的使用
多个消费者绑定到一个队列,同一条消息只会被一个消费者处理
通过设置prefetch来控制消费者预取的消息数量
发布 ( Publish )、订阅 ( Subscribe )
发布订阅模式与之前案例的区别就是允许将同一消息发送给多个消费者。实现方式是加入了exchange(交换机)。
常见exchange类型包括:
Fanout:广播
Direct: 路由
Topic: 话题
发布订阅-Fanout Exchange
Fanout Exchange会将接收到的消息路由到每一个跟其绑定的queue
案例:利用SpringAMQP演示FanoutExchange的使用
实现思路如下:
1.在consumer服务中,利用代码声明队列、交换机,并将两者绑定
2.在consumer服务中,编写两个消费者方法,分别监听fanout.queue1和fanout.queue2
3.在publisher中编写测试方法,向itcast.fanout发送消息
步骤1: 在consumer服务声明Exchange、Queue、 Binding
在consumer服务常见一个类,添加@Configuration注解,并声明FanoutExchange、Queue和绑定关系对象Binding,代码如下
启动后,可以在RabbitMQ控制台看到我们声明的交换机与两个队列完成绑定。
步骤2: 在consumer服务声明两个消费者
在consumer服务的SpringRabbitListener类中,添加两个方法,分别监听fanout.queue1和fanout.queue2
步骤3: 在publisher服务发送消息到FanoutExchange
在publisher服务的SpringAmqpTest类中添加测试方法
项目启动,两个消费者都收到了这个publisher发送的消息
交换机的作用是什么?
接收publisher发送的消息
将消息按照规则路由到与之绑定的队列
发布订阅-DirectExchange
Direct Exchange 会将接收到的消息根据规则路由到指定的Queue,因此称为路由模式 (routes)。每一个Queue都与Exchange设置一个BindingKey
发布者发送消息时,指定消息的RoutingKey
Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
案例:利用SpringAMQP演示DirectExchange的使用
实现思路如下:
1.利用@RabbitListener声明Exchange、Queue、RoutingKey
2.在consumer服务中,编写两个消费者方法,分别监听direct.queue1和direct.queue2
3.在publisher中编写测试方法,向itcast.direct发送消息
步骤1: 在consumer服务声明Exchange、Queue
1.在consumer服务中,编写两个消费者方法,分别监听direct.queue1和direct.queue2.
2.并利用@RabbitListener声明Exchange、Queue、RoutingKey
步骤2: 在publisher服务发送消息到DirectExchange
在publisher服务的SpringAmqpTest类中添加测试方法,convertAndSend的第二个参数就是RoutingKey,如果是red,则两个消费者都可收到,是blue,则只有消费者1收到,yellow则只有消费者2收到。
描述下Direct交换机与Fanout交换机的差异?
Fanout交换机将消息路由给每一个与之绑定的队列
Direct交换机根据RoutingKey判断路由给哪个队列
如果多个队列具有相同的RoutingKey,则与Fanout功能类似
基于@RabbitListener注解声明队列和交换机有哪些常见注解?
@Queue
@Exchange
发布订阅-TopicExchange
TopicExchange与DirectExchange类似,区别在于routingKey必须是多个单词的列表,并且以.分割。Queue与Exchange指定BindingKey时可以使用通配符:
#:代指0个或多个单词
*:代指一个单词
案例:利用SpringAMQP演示TopicExchange的使用
实现思路如下:
1.并利用@RabbitListener声明Exchange、Queue、RoutingKey
2.在consumer服务中,编写两个消费者方法,分别监听topic.queue1和topic.queue2
3.在publisher中编写测试方法,向itcast.topic发送消息
步骤1: 在consumer服务声明Exchange、Queue
1.在consumer服务中,编写两个消费者方法,分别监听topic.queue1和topic.queue2
2.并利用@RabbitListener声明Exchange、Queue、RoutingKey
步骤2: 在publisher服务发送消息到TopicExchange
在publisher服务的SpringAmqpTest类中添加测试方法,如果RoutingKey是china.news,则两个消费者都能够接收到消息,如果为china.weather,则只有消费者1能收到消息,如果是usa.news,则只有消费者2能收到消息
消息转换器
案例:测试发送Object类型消息
说明:在SpringAMQP的发送方法中,接收消息的类型是object,也就是说我们可以发送任意对象类型的消息,SpringAMOP会帮我们序列化为字节后发送
先在consumer中的fanoutConfig中声明一个队列object.queue
在publisher中发送消息以测试
执行完publisher发消息后,RabbitMQ控制台查看object.queue队列中刚收到的消息,看到为乱码,被序列化了
Spring的对消息对象的处理是由org.springframeworkamqp.support.converterMessageConverter来处理的。而默认实现是simpleMessageConverter,基于]DK的ObjectOutputStream完成序列化。
如果要修改只需要定义一个MessaeConverter 类型的Bean即可。推荐用ISON方式序列化,步骤如下:
我们在publisher服务引入依赖
我们在publisher服务声明MessageConverter,在该服务的主启动函数中声明即可。
再次重新执行完publisher发消息后,RabbitMQ控制台查看object.queue队列中刚收到的消息,看到消息已经成为了json格式,而不是乱码了
我们在consumer服务引入Jackson依赖
我们在consumer服务定义MessageConverter,在该服务的主启动函数中声明即可
然后定义一个消费者,监听object.queue队列并消费消息
服务启动后,这个consumer消费者收到了这个json消息。
SpringAMQP中消息的序列化和反序列化是怎么实现的?
利用MessageConverter实现的,默认是JDK的序列化
注意发送方与接收方必须使用相同的MessageConverter
相关文章:

微服务学习|初识MQ、RabbitMQ快速入门、SpringAMQP
初识MQ 同步通讯和异步通讯 同步通讯是实时性质的,就好像你用手机与朋友打视频电话,但是,别人再想与你视频就不行了,异步通讯不要求实时性,就好像你用手机发短信,好多人都能同时给你发短信,你…...

【开源】基于Vue.js的固始鹅块销售系统
项目编号: S 060 ,文末获取源码。 \color{red}{项目编号:S060,文末获取源码。} 项目编号:S060,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…...

SpringCloud微服务网关Gateway:gateway基本实现、断言工厂、过滤器工厂、浏览器同源策略、跨域问题解决方案
Gateway网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0和Project Reactor 等响应式编程和事件流技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API路由管理方式 为什么…...
ArcGIS中如何建立土地利用规划数据库
一、建库步骤 - 收集土地利用规划资料,包括图件资料、数据资料和文本资料。 - 将收集到的数据进行整理和格式转换,使其符合ArcGIS 的数据格式要求。 - 在ArcGIS 中创建新的土地利用规划数据库,并定义相应的数据结构和字段。 - 将转换后的数据导入到新的土地利用规划数据库中…...

微信小程序 服务端返回富文本,图片无法显示
场景: 微信小程序开发中,需要从服务端拿取数据渲染到页面上,后台返回的富文本里,图片路径有时是没有带域名前缀的,导致图片无法正常显示。 解决方案: 在富文本返回时,用正则匹配&#…...
谈谈Redis持久化
目录 前言 RDB AOF 总结 前言 我们都知道Redis 是基于内存的数据库,一旦服务器的进程退出,数据库数据就会随之丢失,这不是我们想看到的,为了避免这个问题,Redis 为我们提供了俩种持久化方案,将数据保存…...
CentOS7中升级OpenSSL详细教程
文章目录 一. 引言二. 升级前的准备1.备份现有配置2. 检查系统版本3. 安装依赖 三. OpenSSL安装四. 验证 一. 引言 OpenSSL: 是用于保护数据安全的重要工具。它能提供加密,解密等多项功能。 然而,随着技术的发展和新的安全漏洞的出现,使用最…...

人工智能基础_机器学习050_对比sigmoid函数和softmax函数的区别_两种分类器算法的区别---人工智能工作笔记0090
可以看到最上面是softmax的函数对吧,但是如果当k = 2 那么这个时候softmax的函数就可以退化为sigmoid函数,也就是 逻辑斯蒂回归了对吧 我们来看一下推导过程,可以看到上面是softmax的函数 可以看到k=2 表示,只有两个类别对吧,两个类别的分类不就是sigmoid函数嘛对吧,所以说 …...
第十九章 解读利用pytorch可视化特征图以及卷积核参数(工具)
介绍一种可视化feaature maps以及kernel weights的方法 推荐可视化工具TensorBoard:可以查看整个计算图的数据流向,保存再训练过程中的损失信息,准确率信息等 学习视频: 使用pytorch查看中间层特征矩阵以及卷积核参数_哔哩哔哩…...

【React】Memo
组件重新渲染时缓存计算的结果。 实例:count1计算斐波那契数列,count2和count1可以触发数值变化。使用memo可以使只有在count1变化时触发斐波那契数列计算函数,而count2变化时不触发斐波那契数列计算函数。 import { useMemo } from "r…...

宣传技能培训1——《新闻摄影技巧》光影魔法:理解不同光线、角度、构图的摄影效果,以及相机实战操作 + 新闻摄影实例讲解
新闻摄影技巧 写在最前面摘要 构图与拍摄角度景别人物表情与叙事远景与特写 构图与拍摄角度案例 主体、陪体、前景、背景强调主体利用前景和背景层次感的创造 探索新闻摄影中的构图技巧基本构图技巧构图技巧的应用实例实例分析1. 黄金分割和九宫格2. 三角型构图3. 引导线构图4.…...

3 时间序列预测入门:TCN
0 引言 TCN(全称Temporal Convolutional Network),时序卷积网络,是在2018年提出的一个卷积模型,但是可以用来处理时间序列。 论文:https://arxiv.org/pdf/1803.01271.pdf 一维卷积:在时间步长方…...
Linux学习笔记-芯片性能检测
文章目录 概述Dhrystone(单核性能测试工具)简介:源码下载:源码编译:使用及输出结果 coremark(多核性能测试工具)简介:源码下载:源码编译:使用及输出结果&…...

2023年网络安全比赛--综合渗透测试②(超详细)
一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将扫描开放的所有端口当作flag提交(例:21,22,23); 2.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将初…...
关于8位图像buffer显示到picturebox上
最终版本: void showbuffer2pictmod4(byte[] buffer, int ww, int hh, PictureBox destImg) { int mod ww % 4;//解决四位对齐问题20150716 int temproiw ww (4 - mod) % 4;//其实这都是和显示相关,处理图像其实不必…...

cocos游戏引擎制作的滚动框地图防止误点操作的简单方法
本篇文章主要讲解,使用cocos creator 来解决在我们日常滚动框开发中,滚动和触摸存在冲突的情况,导致的误触行为的解决办法。 日期:2023年11月25日 具体事项 说明:在我们滚动滚动框时,会出现误点的情况&…...
vue 使用vuex中的data数据引用问题
先上代码: this.userRoleInfo2 this.$store.state.userInfo this.userRoleInfo2.name 111 this.userRoleInfo2.orgName 222 this.userRoleInfo2.orgId 4444问题描述: 博主,定义了一个变量userRoleInfo2来接收了 从vuex中获取了userInfo…...
日志配置的一些思考
日志配置的一些思考 背景说明基础配置抽取子服务扩展配置 背景 基本所有的系统都需要完善的日志配置, 这里是一些常用的配置. 但是没有本地验证, 只能提供一份配置思路. 说明 不可直接用, 会报错, 提供一种配置思路. 不可直接用, 会报错, 提供一种配置思路. 不可直接用, 会报…...

阶梯排列硬币
题意: 你总共有 n 枚硬币,并计划将它们按阶梯状排列。对于一个由 k 行组成的阶梯,其第 i 行必须正好有 i 枚硬币。阶梯的最后一行 可能 是不完整的。 给你一个数字 n ,计算并返回可形成 完整阶梯行 的总行数。 示例 1ÿ…...

HarmonyOS应用开发者高级认证【题库答案】
HarmonyOS应用开发者基础认证【题库答案】 一、判断题 云函数打包完成后,需要到AppGallery Connect创建对应函数的触发器才可以在端侧中调用(错)在column和Row容器组件中,aligntems用于设置子组件在主轴方向上的对齐格式…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...