当前位置: 首页 > news >正文

响应式编程_05 Project Reactor 框架

文章目录

  • 概述
  • 响应式流的主流实现框架
    • RxJava
    • Reactor
  • Project Reactor 框架
    • Reactor 异步数据序列
    • Flux 和 Mono 组件
      • Flux
      • Mono
    • 操作符
    • 背压处理
  • 小结

在这里插入图片描述


概述

响应式编程_02基本概念:背压机制 Backpressure介绍了响应式流规范以及 Spring 框架中的响应式编程技术,也提到了响应式编程框架 Project Reactor。Reactor 是响应式领域中具有代表性的类库,实现了响应式流规范,同时已经成为 Spring 框架生态系统的重要组成部分。


响应式流的主流实现框架

如响应式编程_02基本概念:背压机制 Backpressure中所介绍的 在 Java 领域,目前响应式流的开发库包括 RxJava、Akka、Vert.x 和 Project Reactor 等。这里重点对 RxJava 和 Project Reactor 进行展开描述。

RxJava

说起 RxJava,我们先来讨论它的前缀 Rx。这里的 Rx 代表的是响应式扩展 Reactive Extensions,实际上它最早诞生于微软的 .NET 平台,用来构建高性能的应用系统,其内部集成了异步数据序列的事件驱动编程。

后来,Java 领域也充分借鉴了这一编程模型,诞生了 RxJava 框架,RxJava 可以说是响应式编程得以大规模应用的先驱,推动了一大批针对不同语言的响应式编程框架,这些编程框架同样都以 Rx 作为前缀,例如 RxSwift、RxRuby、RxGo,RxScale、RxKotlin

RxJava 从最初的 1.x 发展到现在的 3.x 版本,各个版本之间变化较大。而从 2.x 版本开始,就对原有的 API 按照响应式流规范进行了重构,并提供了独立的背压功能。

RxJava 应用广泛,例如,在 Netflix 的微服务套件中,熔断器 Hystrix、客户端负载均衡器 Ribbon、API 网关 Zuul 等常用组件中都使用到了 RxJava。除此之外,在以 Android 为代表的 UI 交互开发领域,RxJava 也普遍受到开发人员的欢迎。可以说,其他 Rx 开发库的兴起很大程度上归功于 RxJava 的发展。


Reactor

再来看 Reactor。相较于 RxJava,Reactor 诞生在响应式流规范制定之后,所以从一开始就是严格按照响应式流规范设计并实现了它的 API,这也是 Spring 选择它作为默认响应式编程框架的核心原因

在发展过程中,Reactor 同样经历到从 1.X 到目前 3.X 的演进历程。Reactor 库自早期版本以来已经发展了很多,目前最新的 3.X 版本以 Java 8 作为基线,可以说已经成为业界最先进的响应式库。

RxJava 和 Reactor 二者对比来说,虽然 RxJava 诞生得更早,但 Reactor 应该更有前途。为什么这样说,因为它的开发更活跃,并得到了 Pivotal 公司的大力支持。从 API 角度看,这些库都非常相似,也都提供了一大批非常实用的操作符来简化开发过程。


Project Reactor 框架

Reactor 框架可以单独使用。和集成其他第三方库一样,如果想要在代码中引入 Reactor,要做的事情就是在 Maven 的 pom 文件中添加如下依赖包。

<dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId>
</dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope>
</dependency>
  • reactor-core 包含了 Reactor 的核心功能,
  • reactor-test 则提供了支持测试的相关工具类

接下来我们将从 Reactor 框架所提供的异步数据序列入手,引出该框架所提供的 Flux 和 Mono 这两个核心编程组件以及相关的操作符。最后,作为响应式流的核心,我对它所具备的背压机制进行讨论。

Reactor 异步数据序列

响应式流规范的基本组件是一个异步的数据序列,在 Reactor 框架中,我们可以把这个异步数据序列表示成如下形式。

Reactor 框架异步序列模型

在这里插入图片描述

上图中的异步序列模型从语义上可以用如下公式表示。

	onNext x 0..N [onError | onComplete]

以上公式中包含了三种消息通知,分别对应在异步数据序列执行过程中的三种不同数据处理场景,其中:

  • onNext 表示正常的包含元素的消息通知;

  • onComplete 表示序列结束的消息通知;

  • onError 表示序列出错的消息通知。

当触发这些消息通知时,异步序列的订阅者中对应的这三个同名方法将被调用。正常情况下,onNext() 和 onComplete() 方法都应该被调用,用来正常消费数据并结束序列。如果没有调用 onComplete() 方法就会生成一个无界数据序列,在业务系统中,这通常是不合理的。而 onError() 方法只有序列出现异常时才会被调用


基于上述异步数据序列,Reactor 框架提供了两个核心组件来发布数据,分别是 Flux 和 Mono 组件。这两个组件可以说是应用程序开发过程中最基本的编程对象。

Flux 和 Mono 组件

Flux

Flux 代表的是一个包含 0 到 n 个元素的异步序列

Reactor 官网给出了它的示意图,如下所示。

在这里插入图片描述

上图中的“operator”代表的是操作符,红色的叉号代表异常,而最后的一个符号则代表序列正常结束。显然,序列的三种消息通知都适用于 Flux。

在详细介绍 Flux的构建和使用方法之前,我们先通过一段简短的代码来演示使用 Flux 的方法,如下所示。

private Flux<Account> getAccounts() {List<Account> accountList = new ArrayList<>();Account account = new Account();account.setId(1L);account.setAccountCode("DemoCode");account.setAccountName("DemoName");accountList.add(account);return Flux.fromIterable(accountList);
}

在以上代码中,我们通过 Flux.fromIterable() 方法构建了 Flux<Account> 对象并进行返回

Flux.fromIterable() 是构建 Flux 的一种常用方法.

我们再来看一个 Web 层组件的代码示例,如下所示。

@GetMapping("/accounts")
public Flux<Account> getAccountList() {Flux<Account> accounts= accountService.getAccounts();return accounts;
}

在这个 Controller 提供的 “/accounts” 的端点中,我们调用了 Service 层方法返回了一个 Account 对象列表,它的数据类型也是 Flux<Account>


Mono

Mono 数据序列中只包含 0 个或 1 个元素

在这里插入图片描述

与 Flux 组件一样,我们同样通过一个服务层的方法来演示 Mono 组件的用法,示例代码如下。

private Mono<Account> getAccountById(Long id) { Account account = new Account();account.setId(id);account.setAccountCode("DemoCode");account.setAccountName("DemoName");accountList.add(account);return Mono.just(account);
}

可以看到,这里首先构建一个 Account 对象,然后通过 Mono.just() 方法返回一个 Mono 对象。

Mono.just() 方法是构建 Mono 的最常见用法之一

同样,Web 层组件获取 Mono<Account> 对象的示例端点如下所示。

@GetMapping("/accounts/{id}")
public Mono<Account> getAccountById(@PathVariable Long id) {Mono<Account> account = accountService.getAccountById(id);return account;
}

显然,某种程度上可以把 Mono 看作是 Flux 的一种特例,而两者之间也可以进行相互的转换和融合。

如果你有两个 Mono 对象,那么把它们合并起来就能获取一个 Flux 对象。除此之外,把一个 Flux 转换成 Mono 对象也有很多办法,例如对一个 Flux 对象中所包含的元素进行计数操作就能得到一个 Mono 对象。而这里合并和计数就是针对数据流的一种操作。Reactor 中提供了一大批非常实用的操作符来简化这些操作的开发过程。


操作符

操作符并不是响应式流规范的一部分,但为了改进响应式代码的可读性并降低开发成本,Reactor 库中的 API 提供了一组丰富的操作符,这些操作符为响应式流规范提供了最大的附加值。操作符的执行效果如下所示。

在这里插入图片描述
在 Reactor 中,可以把操作符分成转换、过滤、组合、条件、数学、日志、调试等几大类,每一类中都提供了一批有用的操作符。尤其是针对转换场景,操作符非常健全. 后面介绍 。


背压处理

背压是所有响应式编程框架所必须要考虑的核心机制

Reactor 框架支持所有常见的背压传播模式,包括以下几种。

  • 纯推模式:这种模式下,订阅者通过 subscription.request(Long.MAX_VALUE) 请求有效无限数量的元素。

  • 纯拉模式:这种模式下,订阅者通过 subscription.request(1) 方法在收到前一个元素后只请求下一个元素。

  • 推-拉混合模式:这种模式下,当订阅者有实时控制需求时,发布者可以适应所提出的数据消费速度。

基于这些背压传播模式,在 Reactor 框架中,针对背压有以下四种处理策略。

  • BUFFER:代表一种缓存策略,缓存消费者暂时还无法处理的数据并放到队列中,这时候使用的队列相当于是一种无界队列。

  • DROP:代表一种丢弃策略,当消费者无法接收新的数据时丢弃这个元素,这时候相当于使用了有界丢弃队列。

  • LATEST:类似于 DROP 策略,但让消费者只得到来自上游组件的最新数据。

  • ERROR:代表一种错误处理策略,当消费者无法及时处理数据时发出一个错误信号。

Reactor 使用了一个枚举类型 OverflowStrategy 来定义这些背压处理策略,并提供了一组对应的 onBackpressureBuffer、onBackpressureDrop、onBackpressureLatest 和 onBackpressureError 操作符来设置背压,分别对应上述四种处理策略。

为了更好地展示操作符的语义和效果,引入弹珠图(Marble Diagram)。弹珠图能将数据流的转换以可视化方式呈现出来,它们对于描述操作符的行为非常有效,因此在 RxJavaReactor 等响应式编程框架中,几乎所有的操作符都包含带有对应的弹珠图的说明。 Reactor 官网给出的 onBackpressureBuffer 操作符的弹珠图如下所示。

onBackpressureBuffer 操作符示意图(来自 Reactor 官网)

在这里插入图片描述

onBackpressureBuffer 操作符有很多种可以选择的配置项,我们可以用来灵活控制它的行为。


小结

针对响应式流规范,业界存储了一批优秀的实现框架,而 Spring 默认集成的 Project Reactor 框架就是这其中的代表。Reactor 框架中最核心的就是代表异步数据序列的 Mono 和 Flux 组件, 我们对这两个组件有了一个初步的认识。同时,我们还介绍了 Reactor 中的操作符组件以及针对不同场景的背压处理机制 。

在这里插入图片描述

相关文章:

响应式编程_05 Project Reactor 框架

文章目录 概述响应式流的主流实现框架RxJavaReactor Project Reactor 框架Reactor 异步数据序列Flux 和 Mono 组件FluxMono 操作符背压处理 小结 概述 响应式编程_02基本概念&#xff1a;背压机制 Backpressure介绍了响应式流规范以及 Spring 框架中的响应式编程技术&#xff…...

RabbitMQ 从入门到精通:从工作模式到集群部署实战(一)

#作者&#xff1a;闫乾苓 文章目录 RabbitMQ简介RabbitMQ与VMware的关系架构工作流程RabbitMQ 队列工作模式及适用场景简单队列模式&#xff08;Simple Queue&#xff09;工作队列模式&#xff08;Work Queue&#xff09;发布/订阅模式&#xff08;Publish/Subscribe&#xff…...

导出依赖的几种方法

在 Python 中&#xff0c;你可以使用以下方法导出项目的依赖&#xff1a; 1. 使用 pip freeze pip freeze 可以列出当前环境中安装的所有包及其版本&#xff0c;并将结果保存到 requirements.txt 文件中。 pip freeze > requirements.txt2. 使用 pipreqs pipreqs 可以根…...

CS 与 BS 架构的差异

在数字化的今天&#xff0c;选择软件架构模式对系统的性能、维护、安全和成本都有很大影响。BS架构和CS架构是最常见的两种模式&#xff0c;了解它们的区别和特点对开发人员和企业决策者都很重要。 CS架构最早出现&#xff0c;当时用户直接从主机获取数据。随着客户端和服务端…...

OpenCV YOLOv11实时视频车辆计数线:让车辆进出有条理!

前言 大家好!今天我们聊个超级有趣的课题——如何用OpenCV结合YOLOv11进行实时视频车辆计数。是不是很炫酷?车辆进出全都清晰可见,连“跑车”都能精确统计!不过,别急,这可不仅仅是数车那么简单,背后还有许多实际问题等着你去搞定,比如计数线、车速、误检这些麻烦的小问…...

配置@别名路径,把@/ 解析为 src/

路径解析配置 webpack 安装 craco npm i -D craco/craco 项目根目录下创建文件 craco.config.js &#xff0c;内容如下 const path require(path) module.exports {webpack: {// 配置别名alias: {// 约定&#xff1a; 使用 表示src文件所在路径: path.resolve(__dirname,src)…...

java 进阶教程_Java进阶教程 第2版

第2版前言 第1版前言 语言基础篇 第1章 Java语言概述 1.1 Java语言简介 1.1.1 Java语言的发展历程 1.1.2 Java的版本历史 1.1.3 Java语言与C&#xff0f;C 1.1.4 Java的特点 1.2 JDK和Java开发环境及工作原理 1.2.1 JDK 1.2.2 Java开发环境 1.2.3 Java工作原理 1.…...

Windows Docker笔记-安装docker

安装环境 操作系统&#xff1a;Windows 11 家庭中文版 docker版本&#xff1a;Docker Desktop version: 4.36.0 (175267) 注意&#xff1a; Docker Desktop 支持以下Windows操作系统&#xff1a; 支持的版本&#xff1a;Windows 10&#xff08;家庭版、专业版、企业版、教育…...

hot100(7)

61.31. 下一个排列 - 力扣&#xff08;LeetCode&#xff09; 数组问题&#xff0c;下一个更大的排列 题解&#xff1a;31. 下一个排列题解 - 力扣&#xff08;LeetCode&#xff09; &#xff08;1&#xff09;从后向前找到一个相邻的升序对&#xff08;i,j)&#xff0c;此时…...

DeepSeek辅助学术写作【对比概念】效果如何?

DeepSeek-R1在论文写作细节方面有很多好的应用。我们下面通过具体案例来逐一展示这些功能。 DeepSeek-R1在提问方面&#xff0c;可以简化提示词也能给出精准得答案。我们来一探究竟&#xff01; 对比概念(功能指数:★★★★★) DeepSeek-R1在概念对比方面的功能也非常强大。由…...

基础相对薄弱怎么考研

复习总体规划 明确目标 选择专业和院校&#xff1a;根据你的兴趣、职业规划和自身实力&#xff0c;选择适合自己的专业和院校。可以参考往年的分数线、报录比、复试难度等。了解考试科目&#xff1a;不同专业考试科目不同&#xff0c;一般包括&#xff1a; 公共课&#xff1a…...

kakailio官网推荐的安装流程ubuntu 22.04

https://kamailio.org/docs/tutorials/6.0.x/kamailio-install-guide-git/ # 非必须项 wget -O- https://deb.kamailio.org/kamailiodebkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/kamailio.gpg在/etc/apt/sources.list文件追加以下内容 deb [signed-by/usr/sh…...

DeepSeek:全栈开发者视角下的AI革命者

目录​​​​​​​ DeepSeek&#xff1a;全栈开发者视角下的AI革命者 写在前面 一、DeepSeek的诞生与定位 二、DeepSeek技术架构的颠覆性突破 1、解构算力霸权&#xff1a;从MoE架构到内存革命 2、多模态扩展的技术纵深 3、算法范式的升维重构 4、重构AI竞争规则 三、…...

协同探索与导航文献整理

文章目录 1.SOAR:异构无人机协同探索与拍摄以实现快速自主重建2. RACER: 一种使用分散式无人机群进行快速协同探索的方法3. 使用协作式纳米无人机在非结构化环境中进行最小感知探索4.GVP-MREP:通过动态拓扑图上的 Voronoi 分区进行快速且通信高效的多无人机探索5.森林的快速多无…...

C#结合html2canvas生成切割图片并导出到PDF

目录 需求 开发运行环境 实现 生成HTML范例片断 HTML元素转BASE64 BASE64转图片 切割长图片 生成PDF文件 小结 需求 html2canvas 是一个 JavaScript 库&#xff0c;它可以把任意一个网页中的元素&#xff08;包括整个网页&#xff09;绘制到指定的 canvas 中&#xf…...

AI安全最佳实践:AI云原生开发安全评估矩阵(上)

保护生成式 AI&#xff1a;生成式 AI 安全范围矩阵简介 生成式人工智能&#xff08;生成式 AI&#xff09;正在吸引各大企业的关注&#xff0c;并在全球各行各业中重塑客户体验。这一 AI 能力的飞跃&#xff0c;由数十亿参数的大语言模型&#xff08;LLM&#xff09;和Transfo…...

[ Spring ] Spring Boot Mybatis++ 2025

文章目录 StructureMyBatis Controller AbilitiesConfigure Plugins and RepositoriesApply Plugins and Add DependenciesMyBatis Spring PropertiesMyBatis ApplicationMyBatis BeansMyBatis MapperMyBatis Query Builder Structure this blog introduce 3 ways using mybat…...

JAVAweb学习日记(九) MySQL-事务索引

一、事务-介绍 示例代码&#xff1a; 二、事务-四大特性 三、索引-介绍 无索引&#xff1a;全表扫描&#xff08;对应字段逐一比较&#xff09; 有索引&#xff1a;根据索引结构高效获取数据 优缺点&#xff1a; 四、索引-结构 五、索引-操作语法...

企业加密软件(天锐绿盾)

天锐绿盾是一款功能强大的企业加密软件&#xff0c;以下是对其的详细介绍&#xff1a; 一、产品概述 天锐绿盾&#xff08;又名绿盾信息安全管理软件&#xff09;&#xff0c;专注于企业数据防泄密&#xff0c;致力于为企业提供全方位的数据安全保障。其官网为www.drhchina.c…...

Python实现监督学习与无监督学习

在机器学习中,算法被广泛应用于解决实际问题。监督学习与无监督学习是其中两种重要的学习范式。监督学习通过已标注的数据进行训练,目标是学会预测未知数据的标签。而无监督学习不需要数据的标签,它专注于数据的结构和模式,通常用于聚类或降维等任务。 本教程的目标是帮助…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...