什么是Reactive服务架构

news2024/11/25 13:32:29

介绍:

在java web开发领域,区别于传统的的同步服务架构(底层实现基于同步阻塞IO模型),异步服务这个“新词”(bushi)在不断被提及和重视,不少公司的研发部门也开始在尝试对自己的业务系统进行异步化改造。为了实现和简化异步服务的编程难度,新的编程模式被创造出来,reactive promgraming(中文被翻译成 响应式编程模式),对应的开源实现也有不少,RxJava 、ProjectReactor。基于这些Reactive框架实现的异步服务被称作Reactive 服务。(Ps: reactive 框架内部 定义出来了许多新的概念producer、 consumer、 subscription,一开始学习,真的让人非常头大,难以理解)

所以Reactive 服务属于异步服务的一实现方式,也就是说也可以基于其他技术(比如 java8 CompletableFuture 、guava ListenableFutue)实现异步服务。那问题就主要变成两个了:

  1. 异步服务是什么,它有什么优势?
  2. reactive框架 相对于其他异步实现技术来说,有什么优势?

显然我们更需要理解第一个问题,把握住主要矛盾。下面内容主要分享自己对异步服务的学习和理解,对于第二问题本人还在体会当中。

相关技术
反应堆模式(Reactor)
    同步非阻塞,多工模式,一个事情可以分为几个步骤,每个步骤相应去做,同步串行先做A,后做B

Proactor模式
异步非阻塞,多工模式,A,B,C同时去做,异步去做。

观察者模式(Observer)
     事件通知和监听的模式,也是一种推模式,由服务端推送到客户端。

迭代器模式(Iterator)
     拉模式,服务端准备好数据,由客户端通过循环去获取。

Java并发模型
     WebFlux的底层核心技术是Reactive,Reactive就是关于同步、异步、多工、或者设计模式的综合体。

一、核心概念

  1. 数据流

Reactive技术的核心概念是数据流。数据流是由多个事件构成的异步数据序列,每个事件包括一个值和时间戳。可以理解为一个事件队列,事件的产生和处理都是异步的。

数据流可以是热数据流或冷数据流。热数据流是指在创建后就开始产生事件,即使没有订阅者也会一直产生事件,而冷数据流则是在订阅后才开始产生事件。在实际应用中,数据流的类型取决于应用场景和需求。

  1. 变化传递

Reactive技术通过变化传递,实现数据流的响应式处理。变化传递是指,当数据流中的某个事件发生变化时,整个应用程序会相应地自动更新UI和其他相关组件,无需手动维护和同步。这种自动更新的方式有利于提高应用程序的响应性和性能。

变化传递是通过Observable、Observer、Subject等对象实现的。Observable是数据流的生产者,Observer是数据流的消费者,Subject既是Observable也是Observer,可以同时作为数据流的生产者和消费者。

  1. 异步处理

Reactive技术可以处理异步交互,即在进行网络请求、文件读写等操作时,不会阻塞应用程序的其他部分,从而提高整个应用程序的响应性和性能。异步处理是通过Schedulers、Schedulers.Worker等对象实现的。Schedulers用于指定数据流的线程调度策略,Schedulers.Worker用于在指定线程上执行操作。

  1. 高可扩展性

在Reactive技术中,各个组件之间是通过事件流进行通信的,这使得组件之间的耦合度更低,能够更加容易地进行模块化和复用,从而提高应用程序的可扩展性和可重用性。

二、实现细节

Reactive技术的实现细节与具体的Reactive框架有关。以下以RxJava为例,介绍其实现细节。

  1. 创建Observable

Observable的创建方式有很多种,包括just()、from()、create()等。just()可以创建一个发送特定数据序列的Observable,from()可以将一个Iterable、Array或Future转换为Observable,create()可以自定义Observable的行为。

  1. 订阅Observable

Observable需要通过subscribe()方法订阅,subscribe()方法接收一个Observer作为参数,Observer用于处理Observable发送的事件。

  1. 线程调度

RxJava通过Schedulers对象实现线程调度。Schedulers提供了多种线程调度策略,例如Schedulers.io()表示在I/O密集型操作中使用的线程池,Schedulers.computation()表示在计算密集型操作中使用的线程池。

  1. 操作符

RxJava提供了多种操作符用于转换、过滤、合并等数据流操作。常见的操作符有map()、filter()、flatMap()等。

以上是Reactive技术的核心概念和实现细节的简要介绍,需要根据具体的Reactive框架进行深入学习和实践。

三、异步服务

异步这个词在太多场合出现了,异步服务、java nio api、linux 异步IO模型等等... 。在不同场景下实际含义还有点区别的,导致很多人对java异步服务有错误的理解。我的理解是:异步服务是事件驱动的、基于linux多路复用io模型的web服务

  1. 同步服务缺陷

其实目前基于低版本servlet 规范构建的服务端在部分场景的网络IO已经做到非阻塞了,比如组织请求报文,但是由于低版本servlet 只支持同步处理请求(从方法签名就可以看出,当方法执行完后需返回响应报文),导致线程方面,仍然是 一个线程负责一个请求。如果业务逻辑涉及调用外部接口(rpc)和访问DB时,该线程必须阻塞等待它们返回结果。虽然说线程阻塞时会释放对CPU时间的占用,但是它对内存的占用却没有释放(比如线程的函数调用栈),核心矛盾就在这里。当我们接口的请求并发量暴增后,为了能正常处理每个请求,我们需要使用大量线程,业务逻辑计算的整个过程中,每个线程都一直占用一部分内存,这导致我们需要使用更多内存(硬件资源)。另外线程的切换、创建、释放同样需要占用硬件资源。
一句话来说,就是 目前使用多线程的传统方式处理高并发场景。对线程的使用不够高效,对硬件资源(尤其内存)依赖很大。异步服务则尝试更高效使用线程,使用更少的硬件资源处理更多的用户请求。

// 同步的服务端契约
Response handle(Request request);

// 异步的服务端契约
CompletableFuture<Response> handleAsync(Request request);
Mono<Response> handleAsync(Request request);

2. 异步化改造

异步服务通过少使用线程、以及减少对线程的阻塞,来实现目标。实际方法是要求 服务端以及 所依赖的外部网络服务(rpc调用、访问db)都使用 linux 多路复用 io模型 。

(1)服务入口改造

首先要改的就是handle方法签名,当前线程执行该方法后,返回的是Future。也就是说执行handleAync方法后,相当于提交了一个异步任务,而不是立即获得响应报文。随后我们在Future上在添加一个onSuccess callback方法,该方法主要逻辑是将响应报文发送出去。至此,当前线程执行完所有代码,结束其生命周期,释放所有内存资源。那我们只要保证线程在执行handleAsync内部代码时,没有发生过阻塞,那就是可以说高效率使用了线程。那如何保证这一点,那则需要做到第二点,业务逻辑依赖的所有外部服务必须提供类似的异步接口。

(2)构建全异步调用链路

假设业务逻辑依赖对DB的一次查询,DbService。如果handleAsync调用的是同步的query(),则当前线程会因为网络IO发生阻塞,则又回到原来传统模式,无法“解放”线程。所以我们需要调用的是异步查询的queryAsync。把后续的计算逻辑放到CompletableFuture<Entity>的callback 方法当中。因此,需要要求我们依赖的外部接口必须提供异步方法,构建异步调用链路。

public class DbService{
// 同步查询
Entity query(long id);

// 异步查询
CompletableFuture<Entity> queryAsync(long id);
}

我们使用了外部接口的异步方法,将业务逻辑放到 callback方法中,是异步服务的外在形象,那这些代码什么时候被执行,被什么线程执行,这些线程是否存在阻塞,则是我们要真正掌握的精神内核。

(3)linux 多路复用IO模型

接口的服务端和客户端都使用该模型来解放线程。linux io有关中系统调用 select、epoll等提供了单线程监听多个tcp 连接状态的能力,向select提交tcp连接,包括感兴趣的事件(可读、可写、建立连接成功等),以及事件到达时需要执行的动作。单线程运行的select查询所有连接状态时会阻塞,但是如果有任意一个事件到达时,select便会返回。此时可以起新的线程去执行事件到达的callback方法。这个网络协议的交互使用这种事件驱动的方式进行工作。

这里不详细介绍这种IO模型机理,但是可以看到该模式下,区别同步阻塞IO模型,只有少量线程存在阻塞,执行callback方法的线程生命周期短、不阻塞,实现了更高效的利用线程,对硬件资源的利用率更高。较少的线程就可以提供很大IO吞吐量。

 

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

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

相关文章

【JMM】并发编程Bug的源头——可见性/有序性/原子性问题

本文目录(&#xffe3;∇&#xffe3;)/ 可见性问题 有序性问题 为什么会进行指令重排序/乱序执行&#xff1f; 乱序存在的条件 this对象的溢出 原子性问题 如何保证原子性&#xff1f; synchronized 原理简介 加锁的方式 那么问题来了&#xff0c;JVM是如何知道当前…

2022年中国标准创新贡献奖获奖名单公示,海尔再添两项标准创新奖

01 2022年中国标准创新贡献奖 获奖名单公示 海尔再添两项标准创新奖 近日&#xff0c;2022年中国标准创新贡献奖获奖名单公示。其中&#xff0c;海尔GB/T 28219—2018《智能家用电器通用技术要求》、T/CAS 311.1—2018《电器电子产品绿色供应链管理第1部分&#xff1a;通则》…

前端实现拖拽效果改变元素顺序

文章目录 前言一、实现效果二、拖拽API1.代码2.遇见问题 总结 前言 在一次工作中&#xff0c;前端要实现通过鼠标实现拖拽改变顺序的功能&#xff0c;之前没有接触过拖拽这一块所以刚开始一筹莫展&#xff0c;幸运的是在查阅学习中实现了前端拖拽功能。 一、实现效果 二、拖拽…

月薪从10k到30k,一个普通测试工程师的3年涨薪之路...

“要涨薪&#xff0c;先跳槽”各个行业都存在这一共识&#xff0c;但是任何行业也都没有像程序员这样更为适用且好用的了。 前不久&#xff0c;就有网友分享了自己作为一个普通的自动化测试工程师的三年真实涨薪经历。但看看这个三年涨薪之路&#xff0c;好像并不普通啊&#…

2022年深圳杯数学建模D题复杂水平井三维轨道设计解题全过程文档及程序

2022年深圳杯数学建模 D题 复杂水平井三维轨道设计 原题再现&#xff1a; 在油气田开采过程中&#xff0c;井眼轨迹直接影响着整个钻井整体效率。对于复杂水平井&#xff0c;较差的井眼轨迹很可能会造成卡钻或施加钻压困难等重大事故的发生。因而&#xff0c;在施工之前分析影…

python爬虫-获取某某在线翻译的查询结果,爬取json文件并解析

文章目录 从基础步骤下手正确获取response数据关于url获取方式关于post方法的参数关于payload参数填入运行效果解析json数据到文件中完整代码运行结果 从基础步骤下手 # 指定url # 发出请求&#xff0c;get或post # 获取响应 # 把目标文件转存为字符串形式 # 持久性保存正确获…

从零开始的机械臂yolov5抓取gazebo仿真(六)

项目构造简述 前段时间博主装20.04系统不小心把efi启动给删了&#xff0c;导致18.04系统崩了&#xff0c;所以只能简单讲一下这个项目的设计思路以及以grasp.py代码为例进行简单解析。 yolov5_ros功能包 首先&#xff0c;说一下yolov5_ros功能包&#xff0c;该功能包的作用就…

使用 CameraX 在 Jetpack Compose 中构建相机 Android 应用程序

使用 CameraX 在 Jetpack Compose 中构建相机 Android 应用程序 CameraX 是一个 Jetpack 库&#xff0c;旨在帮助简化相机应用程序的开发。 [camerax官方文档] https://developer.android.com/training/camerax CameraX的几个用例&#xff1a; Image CaptureVideo CapturePrev…

【多线程】什么是线程死锁?形成条件是什么?如何避免?

文章目录 一、什么是线程死锁二、线程死锁三、形成死锁的四个必要条件是什么四、如何避免线程死锁 一、什么是线程死锁 死锁是指两个或两个以上的进程&#xff08;线程&#xff09;在执行过程中&#xff0c;由于竞争资源或者由于彼此通信而造成的一种阻塞的现象&#xff0c;若…

Unity 天空盒

在 Unity 中&#xff0c;天空盒是使用天空盒着色器的一种材质。 创建天空盒材质 1.从菜单栏中&#xff0c;单击 Assets > Create > Material。 2.在 Shader 下拉选单中&#xff0c;单击 Skybox&#xff0c;然后单击要使用的天空盒着色器。 有Skybox/6 Sided、Skybox/…

人民大学与加拿大女王金融硕士项目——在现在憧憬美好的未来

未来是一个虚无缥缈的词汇&#xff0c;抓不住也看不到。未来里有着我们无限的希望&#xff0c;也有着美好的憧憬。未来究竟是怎样的呢&#xff0c;有人说现在的样子里藏着未来的模样。在职的你有没有为未来编织一副美丽的画卷呢&#xff1f;未来很远&#xff0c;远到只能靠想象…

MySQL小记——约束、多表查询

目录 约束 常见约束 主键约束 非空约束 唯一约束 自增长约束 非负约束 外键约束之一对多 外键约束之多对多 多表查询 内连接 外连接 左外连接 右外连接 子查询 自查询 case when语句 约束 在MySQL中&#xff0c;约束是对字段规则的一种限制。 常见约束 1.主…

Linux安装并使用seatunnel2.3.1

SeaTunnel是一个非常易用的超高性能分布式数据集成平台&#xff0c;支持海量数据的实时同步。 下载安装包 设置版本 export version"2.3.1" 通过命令下载 wget "https://archive.apache.org/dist/incubator/seatunnel/${version}/apache-seatunnel-incubat…

Linux/Ubuntu系统运行Python+Yolov5物体识别

程序示例精选 Linux/Ubuntu系统运行PythonYolov5物体识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<Linux/Ubuntu系统运行PythonYolov5物体识别>>编写代码&#xff0c;代码…

汽车最强大脑ECU和单片机是什么关系

摘要&#xff1a; 有效解决线路信息传递所带来的复杂化问题 ECU的定义 ECU原来指的是engine control unit&#xff0c;即发动机控制单元&#xff0c;特指电喷发动机的电子控制系统。但是随着汽车电子的迅速发展&#xff0c;ECU的定义也发生了巨大的变化&#xff0c;变成了elec…

31岁才转行程序员,目前34了,我来说说我的经历和一些感受吧...

最近刷知乎&#xff0c;发现有很多朋友有年龄焦虑了&#xff0c;比如&#xff1a;“我今年28了转行来不来得及”&#xff0c;“我今年30了还能转软件测试吗&#xff1f;”......这种问题在知乎上有很多&#xff0c;仿佛大家都觉得年纪大了&#xff0c;很多事情都来不及了&#…

tps和qps的区别和理解

QPS&#xff08;TPS&#xff09; 并发数/平均响应时间 或者 并发数 QPS*平均响应时间 TPS Transactions Per Second&#xff08;每秒传输的事物处理个数&#xff09;&#xff0c;即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出&#xff0c;加上一次用户数据库访…

html使用elementui案例

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Title</title><!--引入 element-ui 的样式&#xff0c;--><link rel"stylesheet" href"static/css/index.css">…

轻松将Win10系统备份到U盘的2种方法!

问题&#xff1a;我能将Win10系统备份到U盘吗&#xff1f; ​“我想将Win10系统备份到U盘&#xff0c;然后通过增量或差异备份定期备份。我使用了系统自带的工具进行备份&#xff0c;但它无法识别这个U盘。有没有好用的方法可以轻松的将电脑系统备份到u盘/移动硬盘&#xf…

Ubuntu系统下Nginx安装

一、使用apt安装nginx 0-如果本机安装了nginx&#xff0c;就进行卸载&#xff1a; apt-get --purge autoremove nginx 检查本机是否还有nginx程序在后台运行&#xff0c;如果有直接kill掉。 ps -ef | grep nginx 1-默认版本安装 apt-get update apt-get install nginx 2…