从架构师的角度带你把“响应式编程”给一次性搞明白,果然绝绝子
myzbx 2024-12-10 18:26 73 浏览
响应式编程详解
响应式编程是一种基于异步数据流驱动、响应式、使用声明式范式的编程模型,需要遵循一定的响应式编程开发规范,并且有具体的类库实现。响应式编程基于数据流而不是控制流进行业务逻辑的推进。
响应式编程与设计模式
在面向对象编程语言中,响应式编程通常以观察者模式呈现。将响应式流模式和迭代器模式比较,其主要区别是,迭代器基于“拉”模式,而响应式流基于“推”模式。
在命令编程范式中,开发者掌握控制流,使用迭代器遍历“数据”,使用hasNext()函数判断数据是否遍历完成,使用next()函数访问下一个元素。在响应式编程模式中,使用观察者模式,数据由消息发布者(Publisher)发布并通知订阅者(Subscriber),而这种观察者模式本身在基于事件监听机制的响应式系统架构中被广泛使用。Java早期的Swing界面设计也是基于视图事件触发业务响应的系统工作模式。所以,从设计模式的角度讲,响应式编程并不是新鲜事物,只是响应式编程将监听的对象扩展到了更大范围:静态或者动态的Stream数据流,如下图所示。
响应式编程还借鉴了Reactor设计模式,我们通常会在高性能NIO网络通信框架中见到Reactor设计模式的身影,用来实现I/O多路复用。其基本思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上,通过轮询或者边缘触发的方式来处理网络I/O事件。当有新的I/O事件到来或准备就绪时,多路复用器返回并将事件分发到对应的处理器中。Reactor设计模式和响应式编程类似,它们都不主动调用某个请求的API,而是通过注册对应接口,实现事件触发执行,如下图所示。
响应式编程与响应式架构
响应式编程很容易和响应式架构混为一谈。前面我们介绍了响应式宣言中的构建软件架构原则,把符合这些原则的系统称为响应式系统。如果说响应式系统与响应式编程之间具有什么关系,那就是响应式系统的架构风格是响应式的,而响应式编程是实现这个架构风格的最佳实践。从宏观角度看,响应式系统由各种不同组件相互操作、调用组成,共同响应用户请求。响应式系统涉及通信协议、I/O模型、网络传输、数据存储等多方面因素,保障系统在响应力、扩展性、容错、灵活性各方面表现出“实时”“低延迟”“轻量”“健壮”的系统特性。而响应式编程可能是这个大的系统架构下的一部分。另外,响应式系统一般是消息驱动的,而响应式编程是事件驱动的。
消息驱动与事件驱动
响应式宣言指出了两者的区别:“消息驱动”中消息数据被送往明确的目的地址,有固定导向;“事件驱动”是事件向达到某个给定状态的组件发出的信号,没有固定导向,只有被观察的数据。
● 在一个消息驱动系统中,可寻址的接收者等待消息的到来然后响应消息,否则保持休眠状态,消息驱动系统专注于可寻址的接收者。响应式系统更加关注分布式系统的通信和协作以达到解耦、异步的特性,满足系统的弹性和容错性,所以响应式系统更倾向于使用消息驱动模式。
● 在一个事件驱动系统中,通知的监听者被绑定到消息源上。这样当消息被发出时,它就会被调用,所以,响应式编程更倾向于事件驱动。
响应式编程与函数式编程
响 应 式 编 程 同 时 容 易 和 函 数 式 编 程 混 淆 。 函 数 式 编 程(Functional Reactive Programming,FRP)在二十年前就被ConalElliott精确地定义了。在函数式编程中,函数是第一类(firstclass)公民,函数式编程由“行为”和“事件”组成。事件是基于时间的离散序列,而行为是不可变的,是随着时间连续变化的数据。函数式编程与响应式编程相比,它更偏重于底层编码的实现细节。
从Java 8开始,Lambda表达式的引入为Java添加了函数式编程的特性,函数式编程提供了闭包的强大功能。Java中的Lambda表达式通常使用(argument)->(body)语法书写,如下所示:
下面是一些典型的Lambda表达式及其函数式接口:
● Consumer<Integer> c=(int x)->{System.out.println(x)};
● BiConsumer<Integer, String>b=(Integer x, String y)-
>System.out.println(x+":"+y);
● Predicate<String>p=(String s)->{s==null};
在Java 8中新增加了@FunctionalInterface接口,用于指明该接口类型是根据Java语言规范定义的函数式接口。Java 8还声明了一些Lambda表达式可以使用的函数式接口。下面是匿名类和使用函数式编程方式的对比示例。
首先,使用@FunctionalInterface定义一个函数式编程接口。
然后,分别使用内部类和Lambda表达式两种方式执行业务逻辑。
可以看到,在函数式编程中,Lambda表达式允许将一个箭头函数作为参数进行传递,这样的语法表达更加简洁,而本质上由编译器推断并帮助实现转换包装为常规代码。因此,可以用更少的代码来实现相同的功能。而响应式编程的重点是基于“事件流”的异步编程范式,响应式编程通过函数编程方式简化面向对象语言语法的臃肿。响应式编程解决问题的流程是:将一个大的问题拆分为许多独立的小的步骤,而这些小的步骤都可以异步非阻塞地执行;当这些小的子任务执行完,它们会组成一个完整的工作流,并且这个工作流的输入输出都是非绑定的。实现响应式编程的关键就是“非阻塞”,执行线程不会因为竞争一个共享资源而陷入阻塞等待,空耗资源,并且最大化地利用物理资源。
响应式编程与命令式编程模式
响应式编程是一种声明式的编程模型,与之相对应的就是命令模式(线程控制流)的编程模型。大家对命令式编程模式比较熟悉,下面是一段常见的基于命令式编程模式的代码:
上述代码是通过变量的赋值并通过加法计算响应数据之间的对应算数关系结果。但是,这个代码有一个潜在的问题,当我们给这两个变量重新赋值时,第二次的Sum值却没有变化,与我们的期望不符,原因是缺少了执行相加的命令指令。
响应式编程的目的是通过“不可变操作符”固定这种数据,构建数据之间的关系,并正确输出结果,不会因为操作命令的遗忘和缺失导致结果的偏差,造成对应关系和结果错误,下面我们看一下如何使用响应式编程方式来固化这种模式。
下面使用Java 9的Flow API实现两个数的相加功能,按照相同思路,当传入的变量不同时,输出的Sum值也会随着变化,我们把这种对应关系构建为一个声明公式,代码实现如下:
从结果看,响应式编程模式的两次Sum值和输入的数值一致,能够达到预期效果。从这个例子中,我们已经初步接触到了响应式编程中数据源也就是事件发布者(Publisher),还有就是事件的监听回调函数集合——消费者(Subscriber)。消费者会根据next、error、complet触发函数对应关系的执行,以及数据的操作符操作,由于消费者的不可变性,可以根据原生的数据结构生成新的数据结构。相比命令式编程,响应式编程使用操作符表述了一个通用业务执行逻辑,一般可以组合达到预期效果,一般的操作符还包含map、filter、reduce等函数,这里就不再赘述了。
编程范式
“普通的工程师堆砌代码,优秀的工程师优化代码,卓越的工程师简化代码”。
如何写出优雅整洁的代码,不仅是一门学问,也是软件工程的重要一环。在上一节中,我们简单介绍了响应式编程的编程范式,本节我们进一步从开发者的视角、系统的性能、满足用户需求等方面讨论不同编程范式的使用场景和特性优势。
编程范式,又称为编程模型,泛指软件编程过程中使用的编程风格,一般不同的编程范式具有不同的语法特性和差异。目前软件开发技术中常用的典型编程范式有以下几种。
● 命令式编程。
● 面向对象编程。
● 声明式编程。
● 函数式编程。
因为每一个编程范式都有很长的发展历史,在编程语言支持上有不同的标准、组织和语法规范等,本节的目的是希望通过对这些编程范式的介绍,可以帮助我们更好地理解响应式编程范式。
命令式编程
命令式编程是非常传统的软件编程方式,命令式编程由不同的逻辑执行步骤组成,通过一步步指令的执行达到业务逻辑的推进,这种方式也称为过程式编程。命令式编程的执行过程非常符合计算机的执行步骤。C语言是命令式编程的典型代表,它更关注的是机器域底层的内存、指令计算、输入输出。在C语言中,我们经常看到大段的过程式指令、各种if/else/for等控制语句、表达式、数据变量的操作、赋值等指令,这种纯指令开发方式要求开发者对计算机的底层工作原理有非常深刻的理解,而且一个指令出现偏差往往会产生不可预知的错误。同时,命令式编程模式的运维也是难度非常高的。
面向对象编程
面向对象编程可以说是编程领域的一个分水岭,开启了高级程序语言在软件开发上的统治阶段。面向对象编程从问题域出发,将封装、继承、多态的语言特性映射到我们的现实世界。在面向对象编程里,业务问题被抽象成类、接口模板,数据和行为被统一封装在对象内部,作为程序的基本组成单元。面向对象编程范式在提升软件重用性、灵活性和扩展性上比过程式编程更进一步,C++、Java作为面向对象编程语言的代表,屏蔽了机器底层的内存管理和机器域的管理细节。而面向对象编程虽然有较高的开发效率,但是降低了代码的运行效率,这也限制了面向对象编程在性能要求苛刻场景下的应用。
声明式编程
声明式编程受当前“约定优于配置”理念的影响,在软件编程开发领域中被大量应用。声明式编程范式的好处是可以通过声明的方式实现业务逻辑,不需要陷入底层具体的业务逻辑实现细节。声明式编程范式关注的焦点不是采用什么算法或者逻辑来解决问题,而是描述、声明解决的问题是什么。当你的代码匹配预先设定好规则,业务逻辑就会被自动触发执行。
很多标记性语言,如HTML、XML、XSLT,就遵循声明式编程范式,而Spring Boot基于注解方式的编程模型也是声明式编程的一个代表。
Spring框架依赖AOP和IoC编程思想降低了开发者对底层逻辑业务细节的了解程度。例如在Spring Boot中,通过@Transactional注解可以声明一个方法具备事务性的操作,当异常发生时,事务会自动回滚,保证业务逻辑的正常和数据一致性。发生在@Transactional注解背后的实现细节,开发者可以不去关心。
函数式编程
在函数式编程范式中,函数无疑是一等公民,函数式编程最具魅力或者最重要的特性就是不可变性。它的不可变性表现在函数式编程表达式的执行结果,只取决于传入函数的参数序列,不受数据状态变化的影响。
函数式编程中的Lambda在Java 8中被引入,可以看成是两个类型之间的关系:一个输入类型和一个输出类型。Lambda演算就是给Lambda表达式一个输入类型的值,它就可以得到一个输出类型的值。
这个计算过程也是函数式代码对映射的描述,因为函数式代码的抽象程度非常高,所以也意味着函数式代码有更好的复用性。
函数式编程和命令式编程相比,更加关注消息或者数据的传递,而不像命令式编程,关注的是指令控制流。共享数据的状态在多线程环境下会存在资源竞争的情况,往往我们需要把额外的精力投入到冲突地解决、数据状态的维护中。而函数的不可变性保证了数据在传递处理过程中不会被篡改,也不需要依赖外部的锁资源或者状态来维护并发。所以函数式编程在多核处理器中具有天然的并发性,可以最大化地利用物理资源实现并行处理功能。
目前,在JVM体系中,已经出现了越来越多函数式编程范式的语言,例如Scala、Groovy、Clojure等。在当前计算机多核、数据优先、高性能的诉求下,函数式编程具有更广阔的发展前景和未来。然而有利总会有弊,函数式编程的语法相比面向对象编程更晦涩,在大规模工程化的协调配合中,还是需要我们去权衡利弊。因为无论哪种语言范式,本质上都是工具,最终目的都是为业务服务。
本文给大家讲解的内容是响应式微服务架构,响应式编程详解
- 下篇文章给大家讲解的内容是响应式微服务架构,响应式技术框架
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!
相关推荐
- 如何设计一个优秀的电子商务产品详情页
-
加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...
- 怎么在JS中使用Ajax进行异步请求?
-
大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...
- 中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革
-
前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...
- 前端监控 SDK 开发分享_前端监控系统 开源
-
一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...
- Ajax 会被 fetch 取代吗?Axios 怎么办?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...
- 前端面试题《AJAX》_前端面试ajax考点汇总
-
1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...
- Ajax 详细介绍_ajax
-
1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...
- 6款可替代dreamweaver的工具_替代powerdesigner的工具
-
dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...
- 我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊
-
接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...
- 福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光
-
时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...
- 2021年超详细的java学习路线总结—纯干货分享
-
本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...
- 不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!
-
Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...
- 2025 年 Python 爬虫四大前沿技术:从异步到 AI
-
作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...
- 最贱超级英雄《死侍》来了!_死侍超燃
-
死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...
- 停止javascript的ajax请求,取消axios请求,取消reactfetch请求
-
一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)
