响应式流规范解析

在互联网应用构建过程中,我们知道可以采用异步非阻塞的编程模型来提高服务的响应能力。而为了实现异步非阻塞,我们可以引入数据流,并对数据的流量进行控制。我们来考虑一个场景,如果数据消费的速度跟不上数据发出的速度,会发生什么现象呢?让我们来看一下。


显然,如果我们不对生产者生产的数据流量进行控制,那么消费者中的数据就会不断的积压,从而导致出现服务不可用等异常情况。那么如何解决这一问题呢?这就需要引入响应式编程中的一个核心概念,即背压。

背压和响应式流

在数据流中,我们注意到当消费者无法及时处理超过其承受能力的数据量时,需要有一个反馈机制,告知生产者调整生产数据的速度。从数据的流转方向而言,这种反馈机制由位于数据流下游的消费者进行发起,代表着消费者处理数据的压力,所以被称为Back Pressure,翻译成中文就是背压。


一旦有了背压机制,位于下游的消费者就可以通知位于上游的生产者合理控制数据生产的速度,从而确保消费者能够正常处理数据流中的数据。这样,消费者就不会因为数据流量过大而出现问题。

明白了背压的概念,那么问题又来了,如何实现背压呢?这就需要引入一套完整的规范,基于这套规范,开发人员可以获取所有实现背压机制所需要的编程组件,这套规范就是响应式流(Reactive Stream)规范。

响应式流规范为如何实现基于背压的数据流提供了一种事实上的标准。在该规范中,我们通过这样一种机制来实现背压:消费者发送一种异步请求向生产者反馈自己所能处理的数据量,然后生产者同样通过一种异步响应的方式向消费者发送对应的数据量。

响应式流规范

从表现形式上讲,响应式流规范为开发人员提供了一批事先约定好的接口定义。通过这些接口中所包含的各个操作方法,数据流就能从生产者异步传递到消费者。同时,生产者所产生的数据也不会导致消费者无法正常消费。

响应式流是一个非常简洁的规范,只包含了Publisher、Subscriber、Subscription和Processor这四个核心接口。其中Publisher和Subscriber分别充当了生产者和消费者的角色。

我们先来看代表生产者的Publisher接口,该接口的作用就是生成一定数量的数据并进行发送,而发送数据的前提是接收到来自订阅者的请求。

public interface Publisher<T> {

    public void subscribe(Subscriber<? super T> s);

}

可以看到在Publisher接口的subscribe方法中传入了一个Subscriber,这个Subscriber代表的就是订阅者。另一方面,订阅者想要发送订阅请求的前提是需要明确该次请求的数据量,这部分内部被封装在一个订阅令牌中,Subscriber接口的定义如下所示。

public interface Subscriber<T> {

    public void onSubscribe(Subscription s);

    public void onNext(T t);

    public void onError(Throwable t);

    public void onComplete();

}

可以看到在Subscriber接口中包含了一个onSubscribe方法,该方法需要传入代表订阅令牌的Subscription参数。结合Publisher接口和Subscriber接口,我们注意到当执行Publisher接口的subscribe方法时,Subscriber接口的onSubscribe方法就会被执行,这是一种典型的回调处理机制。

而从方法命名上看,Subscriber接口的所有方法都是以on为前缀,代表了对数据流处理过程都是采用了回调处理机制。除了onSubscribe方法之外,onNext回调方法会根据Subscription参数中所包含的请求数量逐一发出数据。数据的发送过程会有两种情况,一种情况是所有数据都成功发送,这时候onComplete回调方法就会被触发;或者是数据发送过程出现了错误,那么就会执行onError回调方法中的处理流程。

接下来,让我们来到前面已经介绍到的Subscription接口。Subscription接口的作用就是一种令牌,相当于在Publisher和Subscriber之间建立了一种请求响应的桥梁,它的定义如下所示。

public interface Subscription {

    public void request(long n);

    public void cancel();

}

显然,Subscription接口的request方法用于向Subscriber请求n个数据,而cancel方法则可以用来对请求过程执行取消操作。

现在,我们已经掌握了响应式流规范中生产者和消费者之间的数据处理流程,让我们回到背压机制,看看在这种处理流程下如何实现背压。在整个数据流处理过程中,处于数据流下游的Subscriber通过Subscription接口的request方法向Publisher请求数据,这就是一种向上反馈的机制,也是实现背压的关键所在。Publisher、Subscriber和Subscription三者之间的交互关系如图所示。


至于响应式流规范中的最后一个接口Processor,它同时具备Publisher和Subscriber接口的所有能力,并提供了对数据流中数据进行转换和处理的能力,定义如下。

public interface Processor<T,R> extends Subscriber<T>,

Publisher<R> {

}

可以看到,Processor可以将来自Subscriber接口的数据类型从T转换为R并返回给Subscriber,这种转换关系如下图所示。


以上四个接口构成了响应式流规范的主体。虽然接口的定义并不复杂,但围绕数据流所展开的交互过程值得我们做进一步的总结。

上图中所示的交互方式共包含7个步骤。

  1. 当Publisher需要执行数据发布操作时,首先需要明确所发布数据的数量,这时候就应该创建一个Subscription接口的实例。
  2. 然后Publisher通过Subscriber的onSubscribe回调方法发送数据,这个过程中需要用到前面所创建的Subscription。
  3. 我们知道Subscription中包含了一个request方法,执行该方法将发起真正的数据请求。
  4. 一旦成功发起请求,Subscriber中的onNext回调方法就会执行,该方法会对发送的数据进行业务处理。
  5. 每当处理完一个数据之后,Subscription的request方法将再次被执行,直到所有数据都发送完毕。
  6. 同样,Publisher继续发送数据,而Subscriber中的onNext回调方法继续处理数据。
  7. 取决于数据发送过程是否顺利结束,系统会触发Subscriber的onComplete或onError回调方法,代表数据流是正常结束还是异常结束。

响应式流规范实现框架

响应式流只是一种规范,而不是一种实现框架或工具。围绕响应式流规范,业界也诞生了一批响应式编程框架,包括Spring 5中所引入的Project Reactor,以及RxJava、Akka和Vert.x等经典框架。

规范的作用就是为所有技术框架提供了一种能够相互协作的兼容模式。基于响应式流规范,开发人员可以在同一个应用程序中综合使用一组响应式编程框架。以Spring 5为例,默认使用了Project Reactor框架,但我们也可以引入RxJava来开发业务代码。下图展示了基于响应式流规范的几种代表性具体技术框架以及它们之间的一种可能交互过程。


对于开发人员而言,掌握如何使用这些响应式编程框架是日常开发过程中的一个方面。更重要的是,我们需要理解和掌握这些框架背后的设计思想和理念,而响应式流规范正是响应式编程思想和理念的精髓所在。

总结

在今天的内容中,我们对响应式流规范的方方面面进行了阐述。我们首先需要明确,数据流处理过程中的流量控制和背压机制是促使响应式流规范诞生的原因,响应式流规范的目的就是为了更好的处理消费者和生产者之间的数据交互过程。同时,我们也注意到想要实现背压机制,需要数据消费者具备一种向上反馈的能力,响应式流规范通过提供一组接口定义了这种能力,包括Publisher、Subscriber、Subscription和Processor。这些接口中的方法并不复杂,但却完整的描绘了整个数据流的高效处理过程。

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

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

相关文章

腺苷调节合成高密度脂蛋白用于三阴性乳腺癌的化学免疫治疗

引用信息 文 章&#xff1a;Adenosine-modulating synthetic high-density lipoprotein for chemoimmunotherapy of triple-negative breast cancer 期 刊&#xff1a;Journal of Controlled Release&#xff08;影响因子&#xff1a;10.8&#xff09; 发表时间&am…

webgl_effects_stereo

ThreeJS 官方案例学习&#xff08;webgl_effects_stereo&#xff09; 1.效果图 2.源码 <template><div><div id"container"></div></div> </template> <script> import * as THREE from three; // 导入控制器 import { …

【乐吾乐2D可视化组态编辑器】实时数据,数据绑定

什么是绑定变量&#xff1f; 绑定变量是指把图元的一个属性与设备数据点关联的一个过程。【注意】只是建立一个数据模型的关联&#xff0c;数据源后面设置。 乐吾乐2D可视化组态编辑器地址&#xff1a;https://2d.le5le.com/ 为什么不直接设置数据源&#xff1f; 方便批量…

AWS-生产级微服务部署架构分享

使用AWS搭建云上应用 名词解释 AWS ECR&#xff1a;AWS ECR 容器存储库&#xff0c;按项目名创建容器仓库&#xff0c;一个项目对应一个仓库&#xff0c;目前是由Jenkins构建镜像远程push到AWS ECR。 **AWS ECS&#xff1a;Amazon Elastic Container Service (ECS) &#xf…

物理安全防护如何创新强化信息安全体系?

物理安全防护是信息安全体系的重要组成部分&#xff0c;它通过保护实体设施、设备和介质等&#xff0c;防止未授权访问、破坏、盗窃等行为&#xff0c;从而为信息系统提供基础的安全保障。要创新强化信息安全体系中的物理安全防护&#xff0c;可以从以下几个方面着手&#xff1…

AI查重与降重:科研人员的新型助手

论文写作低效&#xff1f;试试这四款AI论文工具和降重技术&#xff01;-笔灵 副本 在科研领域&#xff0c;AI写作工具如同新一代的科研利器&#xff0c;它们能够极大提高文献查阅、思路整理和表达优化的效率&#xff0c;本质上促进了科研工作的进步。AI写作工具不仅快速获取并…

k8s AIOps

k8s AIOps 主要介绍下k8sgpt 官站 github 介绍 k8sgpt 是一个用于扫描Kubernetes集群、诊断和分级问题的工具。它以简单的英语呈现问题&#xff0c;并将站点可靠性工程&#xff08;SRE&#xff09;的经验编码到其分析器中。通过AI丰富问题的解释&#xff0c;k8sgpt帮助提取最…

面试题react03

React事件机制&#xff1a; React的事件机制可以分为两个部分&#xff1a;事件的触发和事件的处理。事件的触发&#xff1a;在React中&#xff0c;事件可以通过用户与组件进行交互而触发&#xff0c;如点击、鼠标移动、键盘输入等。当用户与组件进行交互时&#xff0c;浏览器会…

mysql 8 linux7,8安装教程

选择自己对应的linux版本 cat /etc/os-release //查看自己linux系统版本 1.mysql下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 拉到下面找到 选择自己linux指定的版本&#xff0c;否则会很麻烦 cat /etc/os-release //查看系统版本 2.查…

为什么给网站安装SSL证书之后还是有被提示不安全?

分为两种情况一种是安装了付费证书之后还是显示无效&#xff0c;另一种是安装了免费SSL证书的。 付费SSL证书&#xff1a;直接找厂商帮助解决遇到的问题&#xff0c;一般都是有专业的客服来对接这些的。 免费SSL证书&#xff1a;出现这种情况的原因会有很多。因为免费SSL证书的…

代码随想录-二叉树 | 101对称二叉树

代码随想录-二叉树 | 101对称二叉树 LeetCode 101-对称二叉树解题思路代码难点总结 LeetCode 101-对称二叉树 题目链接 代码随想录 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 解题思路 判断&#xff1a; 同时遍历并比较根节点的左、右子树。…

服务器数据恢复—强制上线raid5阵列离线硬盘导致raid不可用的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌2850服务器中有一组由6块SCSI硬盘组建的raid5磁盘阵列&#xff0c;linux操作系统ext3文件系统。 服务器故障&#xff1a; 服务器运行过程中突然瘫痪。服务器管理员检查阵列后发现raid5阵列中有两块硬盘离线&#xff0c;将其中一块硬盘进行…

3、前端本地环境搭建

前端本地环境搭建 安装node [node下载地址] https://nodejs.org/en/download/prebuilt-installer 选择LTS的版本进行下载 下载后直接双击点击&#xff0c;选择自己想要安装到的目录一直点下一步即可&#xff08;建议不要安装到c盘&#xff09; 安装完成后配置环境变量&am…

JSON 无法序列化

JSON 无法序列化通常出现在尝试将某些类型的数据转换为 JSON 字符串时&#xff0c;这些数据类型可能包含不可序列化的内容。 JSON 序列化器通常无法处理特定类型的数据&#xff0c;例如日期时间对象、自定义类实例等。在将数据转换为 JSON 字符串之前&#xff0c;确保所有数据都…

PHP线上文具商城设计与实现-计算机毕业设计源码65198

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对线上文具商城 等问题&#xff0c;对线上文具…

Python 和 Java 实现云计算的最终年项目

1、问题背景 目前&#xff0c;我正在进行我的最终年项目&#xff0c;计划用 Python 编写一个云计算系统&#xff0c;而云客户端将由我的团队成员使用 Java 来编写。这个云客户端将具有一个带有标签的界面&#xff0c;并提供文本编辑器、媒体播放器、几个基于 Java 的小游戏以及…

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048 2024/6/7 13:59 1、背光部分&#xff1a;&backlight { pwms <&pwm2 0 25000 0>; status "okay"; }; &pwm2 { status "okay&…

5、搭建前端项目

5.1 使用vite vue搭建 win r 打开终端 切换到你想要搭建的盘 npm init vitelatest跟着以下步骤取名即可 cd fullStackBlognpm installnpm run dev默认在 http://localhost:5173/ 下启动了 5.2 用vscode打开项目并安装需要的插件 1、删除多余的 HelloWorld.vue 文件 2、安装…

linux驱动学习(七)之混杂设备

需要板子一起学习的可以这里购买&#xff08;含资料&#xff09;&#xff1a;点击跳转 一、混杂设备 混杂设备也叫杂项设备&#xff0c;是对普通的字符设备(struct cdev)的一种封装,设计目的就是为了简化字符设备驱动设计的流程。具有以下特点&#xff1a; 1) 主设备号为10&a…

你工作中最推荐的 C/C++ 程序库有哪些,为什么?

我主要做计算力学&#xff0c;说说平时用的一些c库1、前处理划网格用netgen&#xff0c;非结构网格功能强大&#xff0c;有可执行的软件和供调用的库&#xff0c;使用方便。 刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&…