持续事务管理过程中的事件驱动
比较官方的定义:事件驱动是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。在计算机编程、公共关系、经济活动等领域均有应用。
事件驱动是很早作为术语出现在了 GUI 编程中,比如,用户在界面点击了按钮,就会发送一个 “点击” 事件,而相应的会有一个处理 “点击” 事件的事件处理器会来处理该事件。但实际 GUI 编程对他的定义与我们企业级的框架设计并不处于同一抽象级别。
文章目录
- 一、三种异步通讯方式
- 1、同步与异步
- 2、请求响应的方式
- 3、消息订阅的方式
- 4、使用 Broker 的方式
- 二、事件驱动设计
- 1、关于事件驱动设计
- 2、关于事件驱动与消息驱动
- 3、事件驱动的优缺点
- 4、事件循环器实现
- 三、关于事件驱动架构的 Broker
- 1、进程内 EventBus
- 2、进程外 MQ
一、三种异步通讯方式
1、同步与异步
系统间的通讯方式一般可分为同步通信和异步通信两种,我们可以将将同步通讯理解为打电话,需要实时响应,而异步通信则可理解为发送短信,不需要马上回复。我们往往会在面对超高吐吞量的场景下采取异步通讯,因为这就好比一个人不可能同时接打很多电话,但是他可以同时接收很多的电子邮件一样。
同步调用虽然让系统间只耦合于接口,而且实时性也会比异步调用要高,但是我们也需要知道同步调用会带来如下几个问题:
- 性能和吞吐能力下降:同步调用需要被调用方的吞吐不低于调用方的吞吐,或者说整个同步调用链的性能会由最慢的那个服务所决定;
- 有额外的资源消耗:同步调用会导致调用方一直在等待被调用方完成,如果一层接一层地同步调用下去,所有的参与方会有相同的等待时间。这会非常消耗调用方的资源。因为调用方需要保存现场(Context)等待远端返回,所以对于并发比较高的场景来说,这样的等待可能会极度消耗资源;
- 无法一对多:同步调用只能是一对一的,很难做到一对多;
- 有级联失败问题:同步调用最不好的是,如果被调用方有问题,那么其调用方就会跟着出问题,于是会出现多米诺骨牌效应,故障一下就蔓延开来。
所以,异步通讯相对于同步通讯来说,除了可以增加系统的吞吐量之外,最大的一个好处是其可以让服务间的解耦更为彻底,系统的调用方和被调用方可以按照自己的速率而不是步调一致,从而可以更好地保护系统,让系统更有弹力。
异步通讯通常来说有三种方式:请求响应的方式、消息订阅的方式、使用 Broker 的方式。
2、请求响应的方式
在同步的请求响应下,发送方(sender)会直接请求接收方(receiver),被请求方接收到请求后,直接返回请求方需要的数据。但是在异步的场景下,对于被请求方来说,收到请求后往往是需要一段相对较长的处理事件,是无法直接返回的,对于这种场景,常见的是两种方式:接口轮询、方法回调。
- 接口轮询:发送方不断的去轮询接收方的接口,问一下处理完了没有;
- 方法回调:发送方注册一个回调方法,也就是接收方处理完后回调请求方。这种架构模型在一部分的网上支付中会见到,页面先从商家跳转到支付宝或银行,商家会把回调的 URL 传给支付页面,支付完后,再跳转回商家的 URL。
很明显,这种情况下还是有一定耦合的。是发送方依赖于接收方,并且要把自己的回调发送给接收方,处理完后回调。
3、消息订阅的方式
消息订阅的方式的情况下,接收方(receiver)会来订阅发送方(sender)的消息,发送方会把相关的消息或数据放到接收方所订阅的队列中,而接收方会从队列中获取数据。
这种方式下,发送方并不关心订阅方的处理结果,它只是告诉订阅方有事要干,收完消息后给个 ACK 就好了。
很明显在这种异步通讯的方式下,我们抽出了一种“事件”,并于此同时,达到了无状态服务(Stateless)的目的(请求数据、返回数据,服务里面还可能需要保存调用的状态),这其中有太多的好处,无状态意味着我们可以非常方便地运维。
4、使用 Broker 的方式
对于“消息订阅”方式下,接收方需要向发送方订阅事件,所以是接收方依赖于发送方。这种方式还是有一定的耦合。所以我们可以将事件的承接方抽象出来,这就是使用 Broker 的方式。
所谓 Broker,就是一个中间人,发送方(sender)和接收方(receiver)都互相看不到对方,它们看得到的是一个 Broker,发送方向 Broker 发送消息,接收方向 Broker 订阅消息。如下图所示。
这是完全的解耦。所有的服务都不需要相互依赖,而是依赖于一个中间件 Broker。这个 Broker 是一个像数据总线一样的东西,所有的服务要接收数据和发送数据都发到这个总线上,这个总线就像协议一样,让服务间的通讯变得标准和可控。
二、事件驱动设计
1、关于事件驱动设计
比较官方的定义:事件驱动是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。在计算机编程、公共关系、经济活动等领域均有应用。
事件驱动是很早作为术语出现在了 GUI 编程中,比如,用户在界面点击了按钮,就会发送一个 “点击” 事件,而相应的会有一个处理 “点击” 事件的事件处理器会来处理该事件。但实际 GUI 编程对他的定义与我们企业级的框架设计并不处于同一抽象级别。
上面我们所提到的 “消息订阅” 和 “使用 Broker” 的两种方式都抽象出了事件,并且二者也都是比较著名的事件驱动架构(EDA – Event Driven Architecture),因此事件驱动架构可以使用或不使用消息传递来实现:
- 消息传递是以可靠、有保证的方式将生产者引发的事件传达给消费者的一种方式。特别是当生产者和消费者真正解耦并且可能托管在不同的服务器/虚拟机/环境中并且无法直接访问任何共享内存时。
- 但是在特定情况下——当事件的消费者是在同一个应用程序本身内注册的函数/回调时,或者当消费者需要同步执行时,事件订阅可以在没有消息传递的情况下实现。
2、关于事件驱动与消息驱动
我们常常在提起事件驱动的同时提起消息驱动,并也常将二者做比较并试图找出区别,这里我借用,stackoverflow 上一位答主的回答,这也是我比较信服的:
假设您正在为电子商务网站构建支付服务。下订单时,订单服务将要求您的付款服务授权客户的信用卡。只有当信用卡被授权时,订单服务才会将订单发送到仓库进行包装和运输。
您需要与处理订单服务的团队就信用卡授权请求如何从他们的服务发送到您的服务达成一致。有两种选择。
- 消息驱动:下订单时,订单服务会向您的支付服务发送授权请求。您的服务处理请求并将成功/失败返回给订单服务。初始请求和结果可以同步或异步发送。
- 事件驱动:下订单时,Order 服务会发布一个 NewOrder 事件。您的支付服务订阅了该类型的事件,因此它会被触发。您的服务处理请求并发布 AuthorizationAccepted 或 AuthorizationDeclined 事件。Order 服务订阅这些事件类型。所有事件都是异步的。
由此可以看出,即使对二者含义加以区分时,也不过可以将我们前面提到的 “消息订阅” 和 “使用 Broker” 的两种方式,分别概括为事件驱动与消息驱动。因此笔者的结论是,二者的本质上一致的,都是抽象出了“消息“或”事件”来达到无状态异步调用的目的,只是在实现方式上存在一定差别,而且大部分人对二者认知也不统一,所以在大的场景下,二者可以当作同一回事,即文中所提到的“事件驱动”!
3、事件驱动的优缺点
# 事件驱动编程的优点
- 在大部分的应用场景中,事件编程优与多线程编程;
- 相对与多线程编程来讲,事件驱动编程比较容易,复杂度低,是开发者乐于接受的;
- 大多数的GUI框架,都是使用事件驱动编程了架构的。每一个事件会绑定一个处理器,这些事件通常是点击按钮,选择菜单,等等。处理器r来实现具体的行为逻辑;
- 事件驱动经常使用在I/O框架中,可以很好的实现I/O复用。很多高性能的I/O框架都是使用事件驱动模型的,例如:Netty、Mina、Node.js;
- 易于调试。时间依赖只和事件有关系,而不是内部调度。问题容易暴露。
# 事件驱动编程的缺点
- 构件削弱了自身对系统的控制能力。一个构件触笈事件时,并不能确定响应该事件的其他构件及各构件的执行顺序;
- 不能很好地解决数据交换问题;
- 使系统中各构件的逻辑关系变得更加复杂。
4、事件循环器实现
事件循环器(Event Loop)是一个程序结构,用于等待和发送消息和事件。事件驱动编程的代码核心就是事件循环器,根据实现的方式不同,在网络编程中基于事件驱动主要有两种设计模式: Reactor 和 Proactor。这也分别对应了我们前面提到的 “消息订阅” 和 “使用 Broker” 的两种方式。这里只做简单介绍:
# Reactor 模式
首先来回想一下普通函数调用的机制:
- 程序调用某函数->函数执行
- 程序等待->函数将结果
- 控制权返回给程序->程序继续处理
和普通函数调用的不同之处在于:应用程序不是主动的调用某个 API 完成处理,而是恰恰相反,应用程序需要提供相应的接口并注册到 Reactor 上,如果相应的事件发生,Reactor 将主动调用应用程序注册的接口,这些接口又称为“回调函数”。
# Proactor 模式
在 Proactor 模式下,可以理解为当 I/O 事件触发的一瞬间,I/O事件会自动进入一个队列中,或者说一个容器中。当然进入容器前可能还要做一些处理,比如将数据写入用户指定的缓存区等。而 Proactor 只需要主动地去该容器中取事件,将 IO 完成的信息通知给用户线程。
三、关于事件驱动架构的 Broker
1、进程内 EventBus
EventBus 可以被用来在各种自定义的监听事件中使用,包括不限于 Activity、Fragment、Service 等等等等需要进行数据传递的地方,不过应该只局限于 app 内部。
对于 EventBus ,各种编程语言中都有着自己的实现,这里不做过多赘述!
2、进程外 MQ
目前系统中的异步通信主要是采用消息中间件,消息中间件采用的异步方式为 broker 方式。
比较常见的 MQ 实现:
- ActiveMQ:较早推出的消息中间件,功能强大,社区也非常成熟,有较多的文档。已经在很多公司和项目中得到应用,各种协议支持较好,有多个语言的成熟客户端。主要用于中小型项目的解耦和异步处理。
- RabbitMQ:基于erlang开发,所以并发能力很强,性能极好,延时很低。社区比较活跃,版本迭代较快,有比较稳定的支持。开源提供的管理界面较丰富,用起来很方便,有多个语言的成熟客户端。中小型公司首选(对消息有顺序要求的场景除外)。
- RocketMQ:接口简单易用,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便。可以支撑大规模的topic数量,支持复杂MQ业务场景,经过多次阿里双11大考,可靠性和可用性值得信任。源码是java,我们可以自己阅读源码,定制自己公司的MQ,可以掌控。适合大型互联网应用。
- Kafka:kafka的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展;同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量。社区活动度比较高。用于大数据领域的实时计算、日志采集等场景,是业内标准。
相关文章:

持续事务管理过程中的事件驱动
比较官方的定义:事件驱动是指在持续事务管理过程中,进行决策的一种策略,即跟随当前时间点上出现的事件,调动可用资源,执行相关任务,使不断出现的问题得以解决,防止事务堆积。在计算机编程、公共…...

【手把手一起学习】(三) Altium Designer 20 原理图库添加元件
1 添加元件 元件符号是元件在原理图上的表现形式,主要由边框、管脚、名称等组成,原理图库中的元件管脚(顺序,间距等)与电子元件实物的引脚严格对应,绘制原理图库时,一定参考元件规格书和芯片数据手册中的说明…...

设计模式-行为型模式:观察者模式
目录 1、简介 2、组成部分 3、优缺点 4、使用场景 5、代码实现 1、简介 观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,所有的观察者对象都会得到…...

Springboot 为了偷懒,我封装了一个自适配的数据单位转换工具类
前言 平时做一些统计数据,经常从数据库或者是从接口获取出来的数据,单位是跟业务需求不一致的。 比如, 我们拿出来的 分, 实际上要是元 又比如,我们拿到的数据需要 乘以100 返回给前端做 百分比展示 又比如ÿ…...

正则表达式
当我们需要对字符串进行判断的时候,使用正则表达式能大大提高编程效率。比如,当我们需要找出所有“像邮箱”的字符串(包含"" "." ".com",且顺序一致),我们需要一个某种模式的…...

java进阶Map 集合
通过之前的学习我们知道Map是一个双列集合,就是以键值对的形式进行数据存储 java进阶—集合 Map 下面有 三个子接口,HashMap , HashTable 以及 TreeMap 提醒一点:Map不是Collection下的集合,Collection是单列集合&am…...

Java 方法超详细整理,适合新手入门
目录 一、什么是方法呢? 二、方法的优点 三、带返回值方法定义 语法: 示例: 四、带返回值方法调用 语法: 示例: 五、结果示例 一、什么是方法呢? Java方法是语句的集合,它们在一起执行…...

软考学习笔记(题目知识记录)
答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型,给出问题的解决方案 软件设计可以分为两个阶段: 概要设计阶段和详细设计阶段 结构化设计方法中,概要设计阶段进行软件体系结构的设计&…...

2021.3.3idea创建Maven项目
首先new - project - 找到Maven 然后按下图操作:先勾选使用骨架,再找到Maven-archetype-webapp,选中,然后next填写自己想要创建的项目名,然后选择自己的工作空间①、选择自己下载的Maven插件②、选择选择Maven里的sett…...

ASP.NET MVC | 创建应用程序
目录 首先 NO.1 No.2 App_Data 文件夹 Content 文件夹 Controllers 文件夹 Models 文件夹 Views 文件夹 Scripts 文件夹 最后 首先 一步一步的来,电脑上需要安装vs2019软件,版本高低无所谓,就是功能多少而已。 长这样的࿰…...

思科设备命令讲解(超基础)
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...

Qt-FFmpeg开发-保存视频流裸流(11)
Qt-FFmpeg开发-保存视频流裸流📀 文章目录Qt-FFmpeg开发-保存视频流裸流📀1、概述📸2、实现效果💽3、FFmpeg保存裸流代码流程💡4、主要代码🔍5、完整源代码📑更多精彩内容👉个人内容…...

Zebec官方辟谣“我们与Protradex没有任何关系”
近日,流支付协议Zebec Protocol在其官方推特上,发表了一个辟谣澄清声明。该条推特推文表示,“Zebec 与 Protradex 没有任何关系或产生关联。他们( Protradex )声称Zebec 生态正在支持他们,但这是错误的。随…...

BMS电池管理系统中的各种算法介绍
BMS电池管理系统 是一种用于电池组中的单个电池管理的系统,以确保其安全性、寿命和性能。BMS系统通过采集电池信息并对其进行分析,以确保电池组的正常运行。在BMS电池管理系统中,涉及到了许多算法,包括最大功率点追踪算法、SOC计算…...

stack Overflow 的使用
文章目录优雅的搜索1.1要在特定标签内搜索1.2搜索特定的短语1.3 限定检索位置1.4选择性屏蔽优雅的筛选搜索结果1. 返回的搜索筛选2. 特定时间段的帖子3. 精准的BOOL判断4. 其他的例子优雅的搜索 其实,在Stack OverFlow上的搜索方式,与国内的百度没什么大…...

Vue 在for循环中动态添加类名及style样式集合
介绍 在vue的 for 循环中,经常会使用到动态添加类名或者样式的情况,实现给当前的选中的 div 添加不同的样式。 动态添加类名 提示: 所有动态添加的类名,放在表达式里都需要添加引号,进行包裹。 通过 对象 的形式&a…...

Maven的优势
作用一:个人理解maven主要是用来解决导入java类依赖的jar,编译java项目主要问题。(最早手动导入jar,使用Ant之类的编译java项目)以pom.xml文件中dependency属性管理依赖的jar包,而jar包包含class文件和一些必要的资源文件。当然它可以构建项目…...

uboot,内核,根文件系统的作用
复习了下uboot,内核,根文件系统,简单概括下三者的主要内容。 1 uboot uboot的目的:启动内核。 uboot的功能可以分为两个阶段任务。 1.2.1 uboot第一阶段 uboot第一阶段主要负责硬件相关的初始化,主要在cpu/arm920…...

Vue3通透教程【四】Vue3组合API初体验
文章目录🌟 写在前面🌟 组合式 API 是什么?🌟 直观组合式API🌟 写在最后🌟 写在前面 专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技…...

coco数据集训练nanodet详细流程
github地址 首先要配置环境 conda create -n nanodet python3.8 -y conda activate nanodet确认一下cuda版本 nvcc -V确认是11.3之后,要安装11.3对应的pytorch版本。 本机装pytorch1.12.1后面运行的时候会报错(torch没有经过cuda编译)&…...

关于Kubernetes不兼容Docker
本博客地址:https://security.blog.csdn.net/article/details/129153459 参考文献:https://www.cnblogs.com/1234roro/p/16892031.html 一、总结 总结起来就是一句话: k8s只是弃用了dockershim,并不是弃用了整个Docker…...

MySql_基础篇_从下载mysq到数据库操作
本笔记基于b站up主黑马程序员的视频整理 用于记录与回顾 数据库相关概念 数据库 DS 存储数据的仓库 数据库管理系统 DSMS 操纵和管理数据库的大型软件 sql 操作关系型数据库的编程语言是一套标准 mysql 默认端口号是3306 下载数据库 社区版下载 https://dev.mysql.com/…...

当我尝试问了chatGPT几个问题之后,我感到了危机......
问题1 : vue3 框架的bug有哪些? 组件内部的状态更新不及时:由于Vue3使用Proxy来实现响应式,在某些情况下,组件内部的状态更新不及时,导致组件的渲染出现问题。 组件内部的数据更新不及时:由于V…...

如何生成全局唯一ID
1.数据库自增ID 2.UUID 3.Redis生成ID 4.zookeeper生成ID 5.雪花算法...

基于node vue的电商系统 mongodb express框架
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 基于node vue的电商系统 mongodb express框架前言技术栈基本功能普通用户管理员一、运行截图?二、使用步骤1.前端main.js2.后端admin路由前言 技术栈 本项目采用…...

【03-JVM面试专题-JVM中你知道的类加载器有哪些?作用是什么?分别用来加载什么文件?什么内容的呢?】
JVM中你知道的类加载器有哪些?作用是什么?分别用来加载什么文件?什么内容的呢? JVM的类加载器你都知道吗?它们的作用是什么呢?分别用来加载什么文件呢?你看看自己掌握的怎么样呢? Bo…...

面试纪要FFFFF
面试纪要目录概述需求:设计思路实现思路分析1.主要内容参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive. hap…...

gma 1.1.3 (2023.02.22) 更新日志
(实际版本日期:2023.02.14) 重要更新: 从本版本开始, gma 开始支持 Python 3.11! 新增: 1、map 增加【AddDataSetDiscrete】添加离散型栅格数据集绘制功能。 2、math a、添加 Stretch 数据…...

现有安全技术
现有的安全技术 防火墙技术 数据机密性技术 防火墙技术比较静态地保护网络支付涉及的客户端网络商家网络、金融专用网络等网络级的安全,数据传输过程中的安全性则需要数据机密性技术进一步给以保护 我们将源信息称为明文。为了保护明文,将其通过某种…...

Qt QMAKE_MSC_VER
文章目录摘要修改conf文件参考链接关键字: Qt、 QMAKE_MSC_VER 、 conf、 version、 关键字5摘要 今天在又有了新的小项目需要CV一下,但是第三方提供的是COM组件的库,所以第一步还是老实使用VS版本的Qt 来开发,以防不测…...