什么是响应式编程

我们知道,当系统面对大流量、高并发的访问请求时,就可能会出现一系列性能问题,导致服务丧失了即时的响应性。如何时刻确保系统具有应对请求压力的能力,是架构设计的核心问题之一。

经典的服务隔离、限流、降级以及熔断等机制能够在一定程度上确保系统的响应性。但今天我们要介绍的是构建系统响应性的一种崭新的解决方案,这就是响应式编程(Reactive Programming)。响应式编程打破了传统的同步阻塞式(Blocking)请求响应过程,采用了异步非阻塞式(Non-Blocking)的编程模型,从而提高服务的响应能力。

这里提到了同步阻塞和异步非阻塞这两个核心概念,而正确理解这两个概念是掌握响应式编程的前提条件。接下来,我们首先对这两个概念做必要的展开,来引出响应式编程技术的诞生背景和解决的问题。

为什么需要响应式编程?

如果你使用Spring框架开发过Web应用程序,那么你一定对下面这种开发方式非常熟悉。

public Order getRemoteOrder(String orderNumber) {

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<Order> result= restTemplate.exchange(

"http://orderservice/orders/{orderNumber}", HttpMethod.GET, null, Order.class, orderNumber);

Order order= result.getBody();

processOrder(order);

return order;

}

这是一个查询订单(Order)信息的应用场景,我们使用了Spring中的RestTemplate模板工具类,通过该类所提供的exchange()方法对远程Web服务所暴露的HTTP端点发起了请求。上述实现方式在日常开发过程中非常具有代表性,基于Spring Cloud开发的微服务系统本质上也是通过这种方式完成服务与服务之间的远程调用。但是,上述实现方法实际上存在明显的缺陷,即处理过程是阻塞式的。正是因为同步阻塞的存在才导致了响应式编程技术的诞生和发展。那么,究竟什么是阻塞式呢?让我们首先来对上述代码中的线程模型做进一步分析,看看问题出在哪里。

为了更好的分析整个调用过程,我们假设服务的提供者为服务A,而服务的消费者为服务B,那么这两个服务的交互过程应该这样的。


可以看到,当服务B向服务A发送HTTP请求时,线程B只有在发起请求和响应结果的一小部分时间内在有效使用CPU,而更多的时间则只是在阻塞式地等待来自服务A中线程的处理结果。显然,整个过程的CPU利用效率是很低的,很多时间被浪费在了I/O阻塞上,无法执行其他的处理过程。

更进一步,我们继续分析服务A中的处理过程。如果我们采用典型的三层架构,那么沿着Web服务层->业务逻辑层->数据访问层整个调用链路中,每一步的操作过程都存在着前面描述的线程等待问题。也就是说,整个技术栈中的每一个环节都可能是同步阻塞的。


为了解决同步阻塞问题,可以引入异步非阻塞的相关技术。在Java世界中,一般会采用回调(Callback)和Future这两种机制,但这两种机制都存在一定局限性。回调的核心问题在于处理过程会形成一种嵌套结构,给代码的开发和调试带来很大的挑战。而Future机制本质上是一种多线程技术,大量线程之间的相互协作需要频繁进行上下文切换,同样会导致资源利用效率低下。

通过引入响应式编程技术,我们就可以很好的解决这种类型的问题。响应式编程采用全新的响应式数据流(Stream)来实现异步非阻塞式的网络通信和数据访问机制,能够减低不必要的资源等待时间。那么,所谓的响应式编程到底是什么样子的呢?接下来让我们一起来看一下。

什么是响应式编程?

响应式编程技术的核心是数据流,而数据流又是构建在传统的事件驱动架构与发布订阅模式之上。所以,在引入响应式编程技术之前,我们先来回顾一下发布订阅模式和事件处理相关的技术体系。

发布订阅模式和事件

相信大家对设计模式中经典的观察者模式应该都不陌生。观察者模式拥有一个主题(Subject),以及针对这个主题的一个依赖者列表,这些依赖者被称为观察者(Observer)。而发布订阅(Publish-Subscribe)模式可以认为是对观察者模式的一种改进。在这种模式中,发布者和订阅者相互之间可以没有直接的依赖关系,而是通过发送事件到事件处理平台的方式来完成整合。针对今天开篇中提到的订单查询操作,我们可以基于发布订阅模式进行流程重构。


同样,让我们来到单个服务的内部。在三层架构中,从Web服务层到数据访问层再到数据库的整个调用链路同样可以采用发布订阅模式进行重构。这时候,数据库中的数据一有变化就会通知到上游组件,而不是上游组件通过主动拉取数据的方式来获取数据。


数据流和响应式

显然,上图中异步事件传播的思想可以扩展到整个系统。我们可以想象系统中会存在着很多类似OderEvent这样的事件。每一种事件会基于用户的操作或者系统自身的行为而被触发,并形成了一个事件的集合。我们可以把这个事件的集合看成是一串串连起来的数据流,而系统的响应能力就体现在对这些数据流的即时响应过程上。


对于技术实现过程而言,数据流是一个全流程的概念。也就是说,无论是从底层数据库,到服务层,最后到Web服务层,抑或是在这个流程中所包含的任意中间层组件,整个数据传递链路都应该是采用事件驱动的方式来进行运作。这样,我们就可以不采用传统的同步调用方式来处理数据,而是由处于全流程中的各层组件自行来执行事件。这就是响应式编程的核心特点。

相较传统开发所普遍采用的“拉”模式,在响应式编程下,基于事件的触发和订阅机制,这就形成了一种类似“推”的工作方式。


这种工作方式的优势就在于,生成事件和消费事件的过程是异步执行的,所以线程的生命周期都很短,也就意味着资源之间的竞争关系较少,服务器的响应能力也就越高。这就是响应式编程的精髓,也是解决系统性能问题的关键所在。

讲到这里,你可以会问,我们如何来使用响应式编程技术来开发业务系统呢?不用担心,到目前为止,业界已经诞生了诸如RxJava、Project Reactor、Akka等一大批优秀的响应式编程框架。而在Spring 5中,也引入了WebFlux、Reactive Spring Data等新一代的编程组件来实现响应式Web服务和响应式数据访问。通过这种框架和工具,可以很好的解决传统同步阻塞式处理方式所存在的性能问题。

今天的内容系统分析了传统服务调用存在的问题,从而引出响应式编程概念和实现方法。从技术演进的过程和趋势而言,响应式编程的出现有其必然性。另一方面,响应式编程也不是一种完全颠覆式的技术体系,而是在现有的异步调用、观察者模式、发布订阅模式等的基础上发展起来的一种全新的编程模式,能够会系统带来即时响应性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Istio服务网格的熔断限流实现

在微服务架构的宏大图景中&#xff0c;Istio服务网格如同一位精巧的交通指挥官&#xff0c;它不仅确保了服务间通信的顺畅无阻&#xff0c;还通过先进的熔断与限流机制&#xff0c;为系统的稳定性筑起了一道坚固的防线。接下来&#xff0c;让我们一窥Istio如何在不改动服务代码…

YTM32的flash存储器boot-swap功能详解

YTM32的flash存储器boot-swap功能详解 文章目录 YTM32的flash存储器boot-swap功能详解IntroductionPricinple & MachenisimApplication基本的boot swap用例不更新bootloader的情况更新bootloader的情况 Conclusion Introduction 客户在开发量产型的ECU软件时&#xff0c;大…

并发编程理论基础——管程(并发编程的万能钥匙)(七)

什么是管程 Java采用了管程技术&#xff0c;synchronized关键字及wait()、notify()、notifyAll()三个方法都是管程的组成部分管程和信号量是等价的&#xff0c;管程和信号量之间可以互相实现英文名&#xff1a;Monitor 直译为监视器管程指的是管理共享变量以及对共享变量的操作…

项目性能优化之给dist文件夹中chunk-vendors.js做splitChunks分包,从而减少首屏加载时间

问题描述 我们项目做完,验收通过以后,就需要打包发布上线啦。于是我们执行命令:npm run build打dist包,打包完以后截图如下: 直接打包的chunk-vendors.js太大了 chunk-vendors.js文件太大了,所以我们需要将其优化一下,拆分一下 chunk-vendors.js是啥 chunk-vendors.j…

一种自定义SPI通信协议

本文介绍一种自定义SPI通信协议。 项目开发过程中&#xff0c;有时候会涉及到主处理器或FPGA和MCU之间的SPI通信&#xff0c;涉及到通信就需要考虑通信协议&#xff0c;本文给出一种简单的通信协议。 1.协议格式 协议格式如下图。 其中&#xff0c;将40 bit划分为2大部分&am…

代码随想录训练营Day 69|并查集理论基础、卡码网107.寻找存在的路径

1.并查集理论基础 并查集理论基础 | 代码随想录 并查集可以解决什么问题呢&#xff1f; 主要就是集合问题&#xff0c;两个节点在不在一个集合&#xff0c;也可以将两个节点添加到一个集合中。 注意&#xff1a;求根是求箭头出发的数 路径压缩&#xff1a;求根的根。把根的根的…

【C语言】数据的存储

目录 Ⅰ、数据类型介绍 1.类型的基本归类&#xff1a; Ⅱ、整形在内存中的存储 1 .原码、反码、补码 2. 大小端介绍 3 练习&#xff1a; Ⅲ、浮点型在内存中的存储 1 .浮点数存储规则 本章重点 1. 数据类型详细介绍 2. 整形在内存中的存储&#xff1a;原码、反码、补码 3. …

测试卡无法仪表注册问题分析

1、问题描述 00101测试卡无法注册LTE网络&#xff0c;modemlog中发现终端未发起Attach请求&#xff0c;对比正常注册非正常注册的版本&#xff0c;发现正常的多出了ims apn。可以通过ATCGDCONT?来查询modem APN参数。 2、问题分析 目前Modem是一套&#xff0c;没有相关修改。因…

SpringBoot使用滑动窗口限流防止用户重复提交(自定义注解实现)

在你的项目中&#xff0c;有没有遇到用户重复提交的场景&#xff0c;即当用户因为网络延迟等情况把已经提交过一次的东西再次进行了提价&#xff0c;本篇文章将向各位介绍使用滑动窗口限流的方式来防止用户重复提交&#xff0c;并通过我们的自定义注解来进行封装功能。 首先&a…

vue3 element-plus 实现 table表格合并单元格 和 多级表头

多级表头 数据结构比较复杂的时候&#xff0c;可使用多级表头来展现数据的层次关系。 只需要将el-table-column 放置于el-table-column 中&#xff0c;你可以实现组头。 一般可以直接用官网提供的写法&#xff0c;但是有可能数据会比较多的时候&#xff0c;就需要我们稍微改造…

江门电子行业实施MES系统前后对比

在江门电子行业实施MES系统之前和之后的对比可以涉及以下几个方面&#xff1a; 生产效率提升&#xff1a;实施MES系统后&#xff0c;江门电子行业可以实现生产过程的实时监控和优化&#xff0c;减少生产中的浪费和停机时间&#xff0c;提高生产效率。 质量控制改善&#xff1a;…

【稀疏三维重建】Flash3D:单张图像重建场景的GaussianSplitting

项目主页&#xff1a;https://www.robots.ox.ac.uk/~vgg/research/flash3d/ 来源&#xff1a;牛津、澳大利亚国立 文章目录 摘要1.引言2.相关工作3.方法3.1 背景&#xff1a;从单个图像中重建场景3.2 单目前向的多个高斯 4.实验4.14.2 跨域新视角合成4.3 域内新视图合成 摘要 F…

ONLYOFFICE 桌面编辑器8.1最新版本强势来袭!

文章目录 软件介绍一、安装与界面安装过程用户界面 二、性能与稳定性启动速度与响应时间稳定性 三、兼容性与集成文件格式兼容性第三方集成 四、可支持多人协作五、功能齐全的PDF编辑器六、PDF表单七、文档编辑器中的新增功能八、总结九、自己的建议 软件介绍 在现代办公环境中…

Cell2Sentence:为LLM传输生物语言

像GPT这样的LLM在自然语言任务上表现出了令人印象深刻的性能。这里介绍一种新的方法&#xff0c;通过将基因表达数据表示为文本&#xff0c;让这些预训练的模型直接适应生物背景&#xff0c;特别是单细胞转录组学。具体来说&#xff0c;Cell2Sentence将每个细胞的基因表达谱转换…

解决Windows打开Excel时正在访问打印机问题、复制Word文档卡死的问题

Excel打开打印机问题 取消让windows管理默认打印机 把所有打印机删除&#xff08;粗暴&#xff09; 把windows虚拟打印机设置了默认打印机 控制面板》程序》启用或关闭windows功能》安装“MicrosoftXPS文档写入程序” 把默认打印机改成MicrosoftXPSDocumentWriter 复制W…

如何统计每天新增好友删除好友跟收款

自动统计功能可以了解每天员工添加了多少人&#xff0c;删除了哪些好友&#xff0c;并查看已被删除好友的聊天记录&#xff0c;避免有的员工私下走私单或者转移客户。统计转账是为了避免员工收多报少&#xff0c;或者瞒报。 ​​​

0620所学——环境变量、CMake等

https://www.cnblogs.com/bravesunforever/p/10939078.html CMake&#xff1a; https://zhuanlan.zhihu.com/p/659412062 0621: 学会了在Github里创建组织&#xff0c;把本地仓库“同步”&#xff0c;就可以上传到Github&#xff0c;然后学会了把自己的Repos转移到组织里。G…

Unity的ScrollView滚动视图复用

发现问题 在游戏开发中有一个常见的需求&#xff0c;就是需要在屏幕显示多个&#xff08;多达上百&#xff09;显示item&#xff0c;然后用户用手指滚动视图可以选择需要查看的item。 现在的情况是在100个data的时候&#xff0c;Unity引擎是直接创建出对应的100个显示item。 …

Nest系列 - 4. 连接Mysql数据库以及typeOrm介绍

前面我们使用nest g res xxx 自动生成CRUD的代码&#xff0c;不仅简单&#xff0c;而且只能在本地玩。今天我们就来看nest 如何连接数据库&#xff0c;数据库有很多种&#xff0c;我们今天来看连接最常用mysql 数据库&#xff0c;并且使用typeOrm 进行数据库操作 mysql 安装 …

原装GUVCL-T21GH 韩国Genicom紫外线传感器光电二极管原厂代理商

深圳市宏南科技有限公司是韩国GenUV公司的原厂代理商&#xff0c;所售紫外线传感器均来自于原始生产厂商直接供货&#xff0c;非第三方转售。 韩国GENICOM 紫外线传感器 GUVCL-T21GH 特征&#xff1a; 单供电电压工作 电压输出 高灵敏度和良好的日盲性 尺寸小巧紧凑 韩国GENIC…