什么是反应式编程 - 详解

news/2025/10/14 21:37:35/文章来源:https://www.cnblogs.com/ljbguanli/p/19142086

什么是反应式编程 - 详解

一、什么是反应式编程?一个直观的比喻

想象一下你在使用 Excel 表格。

  1. 你在单元格 A1输入 10

  2. 在单元格 B1输入 20

  3. 在单元格 C1输入公式 =A1+B1

此时,C1会立即反应并显示出结果 30。现在,如果你把 A1的值改为 20C1的值会自动、立即更新为 40

在这个例子里:

  • A1B1数据源

  • C1中的公式是一个声明,它定义了值之间的关系

  • Excel 负责监听A1B1的变化,并在变化发生时自动执行计算来更新 C1

这就是反应式编程的核心思想:​​ 它是一种面向数据流变化传播通过的编程范式。这意味着你能够轻松地表达静态或动态的数据流,并且相关的计算模型会自动地通过数据流来传播变化。


二、核心概念:理解“反应式宣言”与编程模型

要深入理解反应式编程,需要从两个层面来看:系统架构思想(反应式系统)和编程模型(反应式编程库)。

层面一:反应式系统 - 架构目标

《反应式宣言》定义了构建现代云原生应用架构的四个关键特质:

  1. 即时响应​: 系统在任何情况下都应尽可能及时地做出响应,提供一致的服务质量。

  2. 回弹性​: 系统在出现故障时也能保持响应能力。通过复制隔离委托容错等技术实现。

  3. 弹性​: 系统在不同工作负载下都能保持响应能力。能够根据负载动态地增加或减少使用的资源。

  4. 消息驱动​: 反应式系统依赖异步的、非阻塞的消息传递,在组件之间建立边界,确保松耦合、隔离和位置透明性。

反应式编程是建立这种架构目标的重要工具。

层面二:反应式编程模型 - 实现程序

在代码层面,反应式编程通常通过特定的库(如 RxJava, Project Reactor, RxJS)来实现,其核心是围绕“流”的一系列抽象。

三个核心构建块:​

  1. 生产者 / 发布者​: 资料的源头,负责产生事件或数据。它知道在有新数据、错误或任务做完时,需通知哪个消费者

  2. 消费者 / 订阅者​: 数据的处理端,它订阅生产者,并准备接收和处理数据。

  3. 订阅关系​: 连接生产者和消费者的纽带。消费者通过订阅来向生产者表示“我准备好了,请给我数据”。生产者通过这个订阅关系向消费者推送内容。

核心接口:​

在 Project Reactor(Spring WebFlux 的底层库)中,这两个核心接口是:

  • Publisher<T>: 生产者,代表一个可能产生 0 到 N 个连续数据的源。它有一个方法:subscribe(Subscriber<? super T> s)

  • Subscriber<T>: 消费者,包含四个回调方法:

    • onSubscribe(Subscription s): 建立订阅时调用。

    • onNext(T t): 接收到一个新数据时调用。

    • onError(Throwable t): 发生错误或失败时调用。

    • onComplete(): 生产者告知所有数据已发送完毕时调用。

另一个关键接口:Subscription

  • 它代表了一次订阅的生命周期,是控制流的“开关”。Subscriber通过它来向 Publisher请求数据(request(long n))或取消订阅(cancel()),这被称为背压机制的核心。


三、关键特性与优势

  1. 异步与非阻塞

    • 传统代码​: 调用一个方法,线程会阻塞等待结果返回。

    • 反应式代码​: 发起一个请求,线程立即返回去做别的事情。当结果就绪时,会通过回调函数通知你。这极大地提高了资源利用率,尤其适合 I/O 密集型应用(如网络请求、数据库查询)。

  2. 数据流与流处理

    • 你将所有事物都视为“流”:点击事件、HTTP 请求、数据库查询结果、消息等等。

    • 反应式库提供了丰富的操作符,让你可以像处理集合一样(如 map, filter, reduce)来处理这些流,但是以声明式和组合的方式。

  3. 背压 - 流量控制的关键

    • 问题​: 假设生产者生产数据的速度快于消费者处理内容的速度,会导致消费者积压过多数据,最终内存溢出。

    • 解决方案​: ​背压被生产者“推送”淹没。这提供了系统稳定性。就是是反应式编程的核心机制。它允许消费者主动告知生产者“我还能处理多少数据”,从而由消费者来“拉动”数据,而不

  4. 声明式与组合性

    • 代码更像是声明要做什么,而不是如何一步步去做。借助组合各种操作符,你可以构建出非常复杂的数据流处理管道,同时代码依然保持清晰易读。

示例(Project Reactor):​

// 声明一个流:1到10的数字
Flux numberStream = Flux.range(1, 10);
// 声明式地组合操作符来处理流
numberStream.filter(n -> n % 2 == 0)        // 只保留偶数.map(n -> n * n)                // 对每个偶数求平方.subscribe(System.out::println); // 订阅并消费结果(打印)
// 输出:4, 16, 36, 64, 100

四、与相关概念的比较

特性

反应式编程

传统异步回调

响应式 UI

核心

基于数据流的声明式编程范式

基于回调函数的控制流 inversion

一种具体的应用场景(如前端框架)

数据流

核心抽象,提供丰富操作符

需要手动管理,容易形成“回调地狱”

是视图层对数据变化的自动响应

组合性

,通过操作符流畅组合

,回调嵌套难以维护和组合

通常由反应式编程范式驱动

背压

原生支持,是核心特性

需手动完成,非常复杂

通常不涉及

注意​: 前端框架(如 Vue、React)的“响应式”重要指 UI 层能自动响应数据模型的变化,其思想源于反应式编程,但通常不处理背压等复杂流控制难题。


五、优缺点

优点:​

  • 高性能​: 极高的资源利用率,尤其适合处理高并发、高吞吐量的 I/O 密集型场景。

  • 资源高效​: 用少量线程(甚至一个)即可处理大量并发请求。

  • 清晰的错误处理​: 错误可以作为数据流的一部分进行传递和处理。

  • 强大的抽象​: 对于复杂的事件流、异步处理逻辑,反应式编程献出了优雅的抽象。

缺点:​

  • 学习曲线陡峭​: 思维模式的转变和众多操作符的学习需要成本。

  • 调试困难​: 异步调用栈不直观,问题定位比同步代码复杂。

  • 容易滥用​: 并非所有场景都需要反应式,对于便捷的 CRUD 应用,它可能增加了不必要的复杂性。


六、适用场景

  • 微服务网关​: 需要处理大量并发网络请求。

  • 实时应用​: 实时消息推送、聊天室、股票行情系统。

  • 大数据处理​: 处理连续的实时数据流。

  • 高并发后端服务​: 需要高效处理数万甚至数十万并发连接的服务器。

七、常见库与框架

  • Java: ​Project Reactor​ (用于 Spring WebFlux), ​RxJava, ​Akka Streams

  • JavaScript/TypeScript: ​RxJS

  • .NET: ​Reactive Extensions (Rx.NET)​

  • Swift: ​RxSwift

  • Kotlin: ​Flow API​ (在协程基础上)

总结

一种强大的范式,它利用就是反应式编程异步非阻塞数据流背压机制,旨在构建高效弹性响应迅速一个非常值得深入探索的方向。就是的应用程序。它并非银弹,而是解决特定领域(高并发、实时性要求高)问题的利器。当你面临性能瓶颈,需要最大限度地利用计算资源时,反应式编程

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

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

相关文章

SDL3和其附属的编译记录

SDL3的构建记录 环境 windows11 + msys2 + gcc + cmake 编辑器使用vscode,插件为cmake tool,c++和clangd。 子模块 神奇的 sdl3-mixer 还在设计阶段 vcpkg 没有,如果从0构建需要的版本 vcpkg 也不支持。 正常情况下…

Qwen多模态系列模型笔记—Qwen2-VL

方法 Qwen2-VL系列包含三种体量的模型,分别是Qwen2-VL-2B, Qwen2-VL-7B, Qwen2-VL-72B。表1列举出这些模型的超参数和重要信息。值得注意的是,这三个模型视觉编码器始终都采用675M参数量的ViT,没有因模型而改变。此…

k8s Service Nodeport 用于集群外部访问

k8s Service Nodeport 用于集群外部访问 热爱孤独生活

WPF 调用 ChangeWindowMessageFilterEx 修改指定窗口 (UIPI) 消息筛选器的用户界面特权隔离

一、回顾 上一篇博客:记录一下 WPF进程 SendMessage 发送窗口消息进行进程间通信,存在进程权限无法接受消息的问题 - wuty007 - 博客园 说到了 发送端是普通权限的窗体 给 接收端是 管理员权限的窗体,通过 Win32 A…

机器学习比赛

机器学习比赛基本上来就用sklearn的随机森林, 和xgboost库. 2个算法先跑一下.基本能拿到一个能看的结果. 速度都很快. 基本30秒内跑完. 然后再考虑其他的特征工程, 深度学习等等..

牙科诊所借力AI营销4个月创收13万

一个叫Jordan的牙科营销老板用AI在4个月里赚了13万。我来说说他具体怎么做的。 Jordan发现一个问题:英国90%的牙科诊所还在用老旧的预约系统,效率很低。他决定用AI来解决这个问题。 📌 他的做法搭建AI预约系统• 以…

10月14日日记

1.今天上午进行工程实训课程,下午学习英语视听说 2.明天学习离散数学 3.只知道把代码用try-catch包起来,但不清楚应该捕获什么异常,什么时候该抛出(throws),什么时候该处理。搞清楚Error和Exception的区别,Runt…

P4653 [CEOI 2017] Sure Bet

题目描述 现在有 n 个A类灯泡和 n 个B类灯泡,每个灯泡都有各自的权值。 我们将这些灯泡分为 n 组,每组包含一个来自A类的灯泡和一个来自B类的灯泡。 你可以从中选取任意个灯泡,每选取一个灯泡需要花费 1 的代价。 在…

PHP虚拟主机测试页面

<?php /*** PHP 虚拟主机测试页面* 说明:用于测试 PHP 是否正常工作及查看服务器基本信息*/// 设置页面编码 header("Content-Type: text/html; charset=utf-8"); ?> <!DOCTYPE html> <ht…

利用脉冲位宽调制技术和一级滤波电路实现正弦波输出

利用PWM和RC滤波电路输出正弦波 1、初始化硬件 (1)时钟使能RCC,选择外部高速晶振将HCLK配置为最大的84MHz(2)PWM使能TIM1,将PWM设为20KHz,将死区设置为25ns注意:为防止开关不同步导致的短路,需要设置“死区”PWM频…

20251014

今天真是充实的一天!线上工程实训的自学过程十分顺畅,让我轻松掌握了不少知识。理发店的体验也很愉快,发型整理后感觉焕然一新。英语课的学习让我的语言能力有所提升,而晚上的离散数学作业完成得也相当顺利。这一天…

歌词本。 - Slayer

10000h、holy、loveyourself10,000 Hours Do you love the rain does it make you dance When youre drunk with your friends at a party Whats your favorite song does it make you smile Do you think of me When …

使用 Docker 快速搭建 MinIO 文件存储服务

在日常开发中,我们经常需要处理文件上传、下载、存储与访问的场景,比如图片、视频、日志文件、模型数据集等。传统的文件系统难以满足高并发、分布式部署以及云原生化的需求。而 MinIO 作为一款高性能、轻量级、兼容…

2025.10.14 正睿二十连测

正睿二十连测 B 赛场上花了 \(40min\) 写了个暴力。赛后看题解 \(20min\) + 写 \(30min\)。 有多少个长度为 \(n\) 排列,使得 \(x(n - x + 1) \le m\) (\(x\) 为 \(n\) 的位置),答案对 \(p\) 取模。 令 \(f_n\) 表…

singleton_pattern

什么是懒汉单例模式(程序在使用的时候才会构造这个类) 什么是饿汉单例模式(程序启动的时候就构造了这个类) 程序内只存在一个这样的类,不需要重复构造,避免浪费,如读取外部文件,只需一次读取,全局使用。 单例…

20251014周二日记

20251014周二日记今日: 1.上午拿麦当劳去实验室,吃早点开会,写财报。 2.中午不饿没吃,下午上课继续改财报,还要算题。顺便帮忙问问下一届考研的教材问题。 3.晚上和研二师哥师姐一起吃了饭,回实验室学下面的那些…

ai出题

江苏海洋大学考研(340 & 808)思维导图说明:此思维导图以两门自命题大纲为中心,分解为主题 → 子主题 → 关键考点,便于记忆与复习。总览340:鱼类增养殖学 / 鱼类育种学 / 水产动物营养与饲料学(重点:生态养…

Python的Numpy、Pandas和Matplotlib(随笔)

Python--Numpy import numpy as np 1、扩展程序库(维度数组与矩阵运算、针对数组运算提供大量的数学函数库) 2、N维数组对象对象:ndarray(别名array,用于存放同类型元素的多维数组 ,以 0 下标为开始进行集合中元…

财务怎样做到业财融合 - 智慧园区

1. 财务端思维转变 ✅跳出传统账本思维模式:财务人员别只盯着记账、算数据,要多琢磨业务核心逻辑,比如产品提价的原因、项目成本的具体构成。 ✅主动贴近业务全流程:主动参加业务部门的项目会、产品讨论会,把采购…

CF2146E

对于数组 \(a\),定义 \(w(a)\) 为 \(a\) 中满足 \(a_i > mex(a)\) 的下标数。现在给定长度为 \(n\) 的数组,对于每个 \(r\), 求出 \(\max\limits_{l = 1}^{r} w(a[l \sim r])\)。 考虑枚举 \(x = mex(a)\),设 \(…