微服务的异步通信技术RabbitMQ
文章目录
- 前言
- 1.WorkQueue(工作队列)
- 消息预取机制
- 2.Publish&Subscribe(发布-订阅)
- 1.Fanout(广播)
- 2.DirectExchange(路由)
- 3.TopicExchange(话题)
- MQ的优点
前言
MQ的出现进一步降低了微服务模块之间的耦合度,相比于同步通信而言减少了关联服务的等待时间,使消息的传递更加多变,灵活
不管什么东西,只要被Spring整合就会变得十分简单,RabbitMQ也不例外
使用SpringAMQP来实现消息收发,不需要重复地配置连接参数,解决了一部分“硬编码”的问题。可以说和MyBatis整合JDBC非常相似。
在以前,使用原生的RabbitMQ收发消息是这样的:
使用SpringAMQP后收发消息是这样的:
这就是一个基本队列(Basic-Queue)
可以看到,只要引入依赖spring-boot-starter-amqp
,写好yml配置文件,建立连接、创建通道的工作Spring都为我们做好了,而我们要做的仅仅就是利用工具类发送、监听消息,可以说相当的方便!
针对不同的场景,我们要使用不同的队列模型:
1.WorkQueue(工作队列)
对于单一消费者情况(简单队列),当生产者每秒发送50条消息,消费者每秒处理40条消息,这样每秒钟就会多出10条消息无法处理,由此就会产生生产过剩而导致消息堆积在队列中,一旦达到队列内存的上限,新来的消息就无法被处理而被丢弃。
为了提高消息处理的速度,避免队列中消息的堆积可以将队列绑定多个消费者,即WorkQueue
为了方便观察控制台,一般这样设计:
生产者:
@Test
public void testSendMessage2WorkQueue() throws InterruptedException {String queueName = "work.queue";String message = "hello, MQQ";for (int i = 1; i <= 50; i++) {rabbitTemplate.convertAndSend(queueName, message + i);Thread.sleep(20);}
}
消费者:
为了尽可能的模拟真实场景(消费者处理消息的能力不同),所以设置两个消费者的sleep参数为不同的两个时间
@RabbitListener(queues = "work.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {System.out.println("消费者1接收到消息——【" + msg + "】" + "At "+LocalTime.now());Thread.sleep(20);
}@RabbitListener(queues = "work.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {System.err.println("消费者2接收到消息——【" + msg + "】" + "At "+ LocalTime.now());Thread.sleep(200);
}
消息预取机制
运行后观察控制台,发现所有的消息处理完时间竟然花费了差不多五秒钟,很显然这样的效率是非常低下的:
为何绑定了两个消费者消费消息的速度不快反慢了呢?
仔细观察控制台会发现50条消息是被平均分配的,两个消费者分别消费id为偶数、奇数的消息,这样一想好像是处理能力差的消费者拖了后腿(200msX25=5000ms=5s),为什么会出现这样的情况?
这是由于MQ存在消息预取机制,即消费者会在处理之前预先拿到消息的通道,然后逐个处理消息,这个过程是与处理消息相隔离的!
如果还有人不明白就想想使用原生的RabbitMQ时我们是怎么处理消息的:
当执行完回调函数有可能消息都不会被处理,这时程序会继续向下执行,过段时间才会开始处理消息(其实我认为这也是体现RabbitMQ异步的一个地方)
这样的机制存在是保证异步性的关键,通过人为的设置参数也可以将消息预取的方式做出调整,来保证处理的效率,就像这样:
listener:simple:prefetch: 1
通过prefetch参数来保证消费者每次获取消息的个数,以及处理完成后才能获取下一个批次的消息
进行数据预取设置后消费者在一秒之内处理完了所有的消息:
由此可见对于WorkQueue中消费者的设置要进行“按劳分配”的策略才较为完美
使用工作队列WorkQueue之后处理消息的效率得到了很大的提升,并且也不会出现消息堆积的情况
2.Publish&Subscribe(发布-订阅)
对于简单队列和工作队列模型,生产者发布消息,消费者一旦消费完,消息就会被销毁。这样无法做到将一个消息同时发送给多个消费者。
对于一个微服务项目,在支付订单的模型中当支付服务完成,会发消息同时去通知短信服务、订单服务…这就需要保证消息的高可用,不能一个服务消费完消息就被销毁而导致其他服务接收不到消息
如何做到将同一消息发送给多个消费者并让其各自接收到?采用发布&订阅的工作模型即可
通过交换机(exchange)将消息路由到不同的队列中,再由消费者来消费各自订阅队列中的消息
针对不同的交换机种类会有不同的发布策略:
1.Fanout(广播)
SpringAMQPA提供了声明交换机、队列、绑定关系的API
所以使用Exchange接口下的实现类就可以实现将消息路由到每一个绑定的Queue中,使用代码就会变得非常简单,声明交换机并绑定队列即可:
@Bean
public FanoutExchange fanoutExchange(){return new FanoutExchange("yu7.fanout");
}// fanout.queue1
@Bean
public Queue fanoutQueue1(){return new Queue("fanout.queue1");
}// 绑定队列1到交换机
@Bean
public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
}// fanout.queue2
@Bean
public Queue fanoutQueue2(){return new Queue("fanout.queue2");
}// 绑定队列2到交换机
@Bean
public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
}
注意:交换机只能用作消息的转发路由,不能用作消息的存储,一旦路由失败消息就会丢失!
2.DirectExchange(路由)
DirectExchange会将接收到的消息根据规则路由到指定的Queue中,生产者发布消息时指定消息的RoutingKey与消费者声明的bindingKey相匹配,从而达到“精确制导”
为了简化开发不使用声明Bean的方式来完成配置,通过@RabbitListener注解即可一键完成,所以根本不需要使用配置类:
生产者:
@Test
public void testSendDirectExchange() {// 交换机名称String exchangeName = "yu7.direct";// 消息String message = "hello, MQ!";// 发送消息rabbitTemplate.convertAndSend(exchangeName, "A", message);
}
消费者:
@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),exchange = @Exchange(name = "yu7.direct", type = ExchangeTypes.DIRECT),key = {"A", "B"}
))
public void listenDirectQueue1(String msg){System.out.println("消费者接收到direct.queue1的消息:【" + msg + "】");
}@RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),exchange = @Exchange(name = "yu7.direct", type = ExchangeTypes.DIRECT),key = {"A", "C"}
))
public void listenDirectQueue2(String msg){System.out.println("消费者接收到direct.queue2的消息:【" + msg + "】");
}
当队列的bindingKey都相同时就变成了广播模型
3.TopicExchange(话题)
Topic与Direct非常相似,他允许RoutingKey-BindingKey以通配符的形式进行匹配,这样就可以更加有针对性的路由、订阅更多消息,并且以前用多个BindingKey的情况现在只需要用一个就能解决:
#:代表0或者多个单词
*:代指一个单词
MQ的优点
1、耦合度低:每次有新需求,只需要添加对应的订阅即可
2、吞吐量提升:各自处理自己订阅的事件,不需要等待执行完毕后再释放资源
3、故障隔离:因为没有强依赖,中间某一环节出了问题,不会影响整个流程
4、流量削峰:MQ就像—根管道,大量请求来了,你们给我排好队,依次执行
相关文章:
微服务的异步通信技术RabbitMQ
文章目录前言1.WorkQueue(工作队列)消息预取机制2.Publish&Subscribe(发布-订阅)1.Fanout(广播)2.DirectExchange(路由)3.TopicExchange(话题)MQ的优点前…...
Word处理控件Aspose.Words功能演示:使用 C++ 在 Word (DOC/DOCX) 中添加或删除水印
Aspose.Words 是一种高级Word文档处理API,用于执行各种文档管理和操作任务。API支持生成,修改,转换,呈现和打印文档,而无需在跨平台应用程序中直接使用Microsoft Word。此外, Aspose API支持流行文件格式处…...
chatGPT模型原理
文章目录简介BertGPT 初代GPT-2GPT-3chatGPT开源ChatGPT简介 openai 的 GPT 大模型的发展历程。 Bert 2018年,自然语言处理 NLP 领域也步入了 LLM 时代,谷歌出品的 Bert 模型横空出世,碾压了以往的所有模型,直接在各种NLP的建模…...
四、阻塞队列
文章目录基础概念生产者消费者概念JUC阻塞队列的存取方法ArrayBlockingQueueArrayBlockingQueue的基本使用生产者方法实现原理ArrayBlockingQueue的常见属性add方法实现offer方法实现offer(time,unit)方法put方法消费者方法实现原理remove方法poll方法poll(time,unit)方法take方…...
企业电子招投标采购系统源码之登录页面
信息数智化招采系统 服务框架:Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构:VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术:Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…...
SQL零基础入门学习(十三)
上一篇(SQL零基础入门学习(十二)) SQL 视图(Views) 视图是可视化的表。 SQL CREATE VIEW 语句 在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表。 视图包含行和列,就像一个…...
Java实现简单KV数据库
用Java实现一个简单的KV数据库 开发思路: 用map存储数据,再用一个List记录操作日志,开一个新线程将List中的操作写入日志文件中,再开一个线程用于网络IO服务接收客户端的命令,再启动时检查日志,如果有数据就…...
【Spark分布式内存计算框架——Spark Streaming】5. DStream(上)
3. DStream SparkStreaming模块将流式数据封装的数据结构:DStream(Discretized Stream,离散化数据流,连续不断的数据流),代表持续性的数据流和经过各种Spark算子操作后的结果数据流。 3.1 DStream 是什么…...
Spring系列-9 Async注解使用与原理
背景: 本文作为Spring系列的第九篇,介绍Async注解的使用、注意事项和实现原理,原理部分会结合Spring框架代码进行。 本文可以和Spring系列-8 AOP原理进行比较阅读 1.使用方式 Async一般注解在方法上,用于实现方法的异步…...
Python自动化测试实战篇(6)用PO分层模式及思想,优化unittest+ddt+yaml+request登录接口自动化测试
这些是之前的文章,里面有一些基础的知识点在前面由于前面已经有写过,所以这一篇就不再详细对之前的内容进行描述 Python自动化测试实战篇(1)读取xlsx中账户密码,unittest框架实现通过requests接口post登录网站请求&…...
Linux 进程:父子进程
目录一、了解子进程二、创建子进程1.创建子进程2.区分父子进程三、理解子进程四、创建子进程的意义进程就是运行中的应用程序,如果一个程序较为庞大,我们可以给这个程序创建多个进程,每个进程负责一部分代码的运行。 A进程如果创建了B进程&am…...
Unity 之 实现读取代码写进Word文档功能实现 -- 软著脚本生成工具
Unity 之 实现读取代码写进Word文档功能前言一,实现步骤1.1 逻辑梳理1.2 用到工具二,实现读写文件2.1 读取目录相关2.2 读写文件三,编辑器拓展3.1 编辑器拓展介绍3.2 实现界面可视化四,源码分享4.1 工具目录4.2 完整代码前言 之所…...
Typora图床配置:Typora + PicGo + 阿里云OSS
文章目录一、前景提要二、相关链接三、搭建步骤1. 购买阿里云对象存储OSS2. 对象存储OSS:创建Bucket3. 阿里云:添加OSS访问用户及权限4. 安装Typora5. 配置PicGo方法一:使用PicGo-Core (Command line)方法二:使用PicGo(app)6. 最后…...
二进制搭建以太坊2.0节点-2023最新详细版文档
文章目录 一、配置 JWT 认证二、部署执行节点geth2.1 下载geth二进制文件2.2 geth节点启动三、部署共识节点Prysm3.1 下载Prysm脚本3.2 Prysm容器生成四、检查节点是否同步完成4.1 检查geth执行节点4.2 检查prysm共识节点4.3 geth常用命令五、节点同步详细说明5.1 启动时日志5.…...
如何简化跨网络安全域的文件发送流程,大幅降低IT人员工作量?
为什么要做安全域的隔离? 随着企业数字化转型的逐步深入,企业投入了大量资源进行信息系统建设,信息化程度日益提升。在这一过程中,企业也越来越重视核心数据资产的保护,数据资产的安全防护成为企业面临的重大挑战。 …...
带你深入了解c语言指针后续
前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨在该…...
借助Intune无感知开启Bitlocker
希望使用 Intune 部署 BitLocker,但不知道从哪里开始?这是人们最开始使用 Intune 时最常见的问题之一。在本博客中,你将了解有关使用 Intune 管理 BitLocker 的所有信息,包括建议的设置、BitLocker CSP 在客户端上的工作方式&…...
零基础该如何转行Python工程师?学习路线是什么?
最近1年的主要学习时间,都投资到了 python 数据分析和数据挖掘上面来了,虽然经验并不是十分丰富,但希望也能把自己的经验分享下,最近也好多朋友给我留言,和我聊天,问我python该如何学习,才能少走…...
Go项目(商品微服务-1)
文章目录简介建表protohandler商品小结简介 商品微服务主要在于表的设计,建哪些表?表之间的关系是怎样的? 主要代码就是 CURD表和字段的设计是一个比较有挑战性的工作,比较难说清楚,也需要经验的积累,这里…...
机器学习——集成学习
引言 集成学习:让机器学习效果更好,单个不行,群殴走起。 分类 1. Bagging:训练多个分类器取平均(m代表树的个数)。 2.Boosting(提升算法):从弱学习器开始加,通过加权来进行训练。…...
VS编译系统 实用调试技巧
目录什么是bug?调试是什么?有多重要?debug和release的介绍windows环境调试介绍、一些调试实例如何写出(易于调试)的代码编程常见的错误什么是bug?其实bug在英文翻译中有表示臭虫的含义,因为第一次被发现的导致计算机…...
【华为OD机试模拟题】用 C++ 实现 - GPU 调度(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明GPU 调度题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。...
腾讯前端必会react面试题合集
React-Router的路由有几种模式? React-Router 支持使用 hash(对应 HashRouter)和 browser(对应 BrowserRouter) 两种路由规则, react-router-dom 提供了 BrowserRouter 和 HashRouter 两个组件来实现应用的…...
Linux搭建SVN服务器,并内网穿透实现公网远程访问
文章目录1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6.2 配置…...
C++STL之list的模拟实现
目录 一.list准备 二. iterator迭代器 1._list_iterator 2.begin()、end() 3.const_begin()、const_end() 4.!&& 5. && -- 6.operator* 7.operator-> 三.Modify(修改) 1.insert() 2.erase() 3.push_back() && push_front() 4.pop_bac…...
为什么硬件性能监控很重要
当今的混合网络环境平衡了分布式网络和现代技术的实施。但它们并不缺少一个核心组件:服务器。保持网络正常运行时间归结为监控和管理导致网络停机的因素。极有可能导致性能异常的此类因素之一是硬件。使用硬件监控器监控网络硬件已成为一项关键需求。 硬件监视器是…...
HTTP缓存
HTTP缓存HTTP缓存引发的一个问题HTTP缓存的作用HTTP缓存的分类强制缓存协商缓存(解决强缓存下资源不更新问题)缓存策略HTTP缓存引发的一个问题 有一次在开发移动端H5项目,UI提了几个UI问题,经过样式调试,android上没有…...
SPI设备树处理过程
SPI设备树处理过程 文章目录SPI设备树处理过程参考资料:一、 spi_device结构体二、 SPI设备树格式2.1 SPI Master2.2 SPI Device2.3 设备树示例三、设备树实例3.1 使用GPIO模拟的SPI控制器3.2 IMX6ULL SPI控制器四、 设备树处理过程致谢参考资料: 内核头…...
数据有哪些重要的作用?
我们正处在科技高速发展的时代,如今互联网已经与我们的生活息息相关,我们每天在互联网产生大量的数据,这些数据散落在网络中看似没有怎么作用,但是这些数据经过系统的处理整合起来确实非常有价值的。 一、 发展大数据技术可以提高…...
spring面试题总结
1、spring是什么? spring是一个轻量级IOC和AOP容器框架,是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用的开发,开发者只需要关注业务需求即可: core container 容器组件 spring context,…...
做网站天通苑/网络营销策划书
数据插值方法x测试结果2.拟合方法Polyfit Function[p,s]polyfit(x,y,n);返回多项式系数向量p和矩阵s,s与polyval函数一起用时,可以得到预测值的误差估计。[p,s,mu]polyfit(x,y,n);返回多项式的系数,利用该函数进行多项式曲线拟合评价。Polyva…...
网站轮播效果怎么做的/东莞seo网站制作报价
函数:startswith()作用:判断字符串是否以指定字符或子字符串开头一、函数说明语法:string.startswith(str, beg0,endlen(string))或string[beg:end].startswith(str)参数说明:string: 被检测的字符串str: …...
移动互联网站开发与维护/网络营销企业网站优化
工作时长两年的算法工程师来答一波!学习方向主要分为 4 个部分:数学基础、编程能力、算法基础、实战。1、数学基础在机器学习算法中,涉及到最为重要的数学基本知识有两个:线性代数和概率论。这两也是大学的必修课了,如…...
用区块链来做网站/查询网站信息
倪光南院士一再警告国内企业需要加强自主技术研发,国内企业曾不屑一顾,但是随着2019年以来华为的遭遇终于让国内企业重视芯片技术研发了,如今又一家中国芯片企业再次打破了空白,研发出拥有自主知识产权的模拟芯片,打破…...
短网址生成设计/搜索引擎优化需要多少钱
后台系统所用的技术 框架:Spring SpringMVC Mybatisdubbo 前端:EasyUI 数据库:mysql 系统间通信 由于淘淘商城是基于SOA的架构,表现层和服务层是不同的工程。所以要实现商品列表查询需要两个系统之间进行通信。 如何实现远程通…...
网站建站对象/快速搭建网站的工具
K-means聚类算法(事先数据并没有类别之分!所有的数据都是一样的)1、概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成…...