何为响应式编程
响应式编程是一种面向数据流和变化传播的编程范式,数据更新是相关联的。 这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
以响应式编程方式进行思考,意味着要放弃命令式且带状态的编程习惯,并且强迫你的大脑以一种不同的方式去工作。
响应式编程提高了代码的抽象层级,所以你可以只关注定义了业务逻辑的那些相互依赖的事件,而非纠缠于大量的实现细节。它可以简化项目,特别是处理嵌套回调的异步事件、复杂的列表过滤和变换,或时间相关问题。
交互式编程与响应式编程
平时我们使用最多的便是“交互式(Interactive)”的编程方式,采用的是组件之间的相互调用来表现逻辑。例如,对象A向对象B请求数据并等待返回,待对象B完成并返还数据之后A才继续进行后面的操作。
响应式编程是一种基于“改变”的编程方式。例如在交互式编程中,A = B + C这样的表达式意味着将B与C之和赋给A,而此后B与C的改变都与A无关。而在响应式编程中,A会去“响应”B或C的变化,即一旦B或C改变之后,A的值也会随之变化。响应式编程的一个典型应用便是GoF23中的观察者模式。
响应式系统模型
Actor模型
Actor模型=数据+行为+消息。Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,这样就保证Actor内部数据只有被自己修改。
Actor是一个个独立的实体,他们之间是毫无关联的。但是,他们可以通过消息来通信。一个Actor收到其他Actor的信息后,它可以根据需要作出各种相应。Actor的常见应用模式是处理大规模并发输入流:将具体工作分类给异步的工作节点,之后返回工作节点计算的结果。
Actor模型实际上并不是纯正的函数式编程模型。Receive方法返回Unit类型,这意味着在该方法中,所有事情都是通过副作用完成的。再者,只要需要,Actor模型便会允许使用可变状态,但这里要遵守一个规则,将状态封装在某个actor中,并确保所有状态的响应操作是线程安全的。
综上,Actor模型是处理大规模、高度可用、事件驱动应用程序的更为通用的方法。
函数响应式编程(functional reactive programming,FRP)
在函数响应式编程模型中,基于时间的状态需要通过某一系统传播到需要使用这些状态的代码中。当FRP模型中的某一状态发生变化时,你并不需要手动地对依赖这些变化的变量进行更新,与之相反,FRP会使用声明的方式描述数据元素之间的依赖关系,而FRP运行时则会负责状态的传播。因此,用户使用函数式声明语句和组合语法编写代码。
FRP基本上就是面向异步事件流的编程了,这个异步事件流(Stream)是一个按时间排序的事件序列。Stream是不可变的,任何操作都返回新的Stream,且它是一个Monad。
响应式扩展(reactive extensions,Rx)
Reactive Extension 这个概念最早出现在.net社区的Rx.net,一个提供处理异步事件的程序库,其核心概念是Observable,表示有限或者无限多个现在或者将来到达的事件。Observable提供了onNext,onError,onCompleted供开发者定制新元素到达,出现错误,或者流结束时的程序的行为。并提供了List上类似的操作,如map,filter,reduce,大大降低了异步事件编程的复杂度。
因为这些概念是如此的强大,以至于很多编程语言,如java,ruby,javascript很快就有了各自的reactvie extension。
Rx模型中的可观察序列代表事件流或其他数据源。通过将可观察序列与LINQ(language-integrated query,语言集成查询)库提供的查询操作符(组合器)拼接起来,Rx组成了异步程序。
小结
Actor、FRP以及Rx都是基于事件的系统模型。FRP和Rx模型更像是一个处理各类事件流的管道系统,而Actor模型则像是一个包装各个组件进行交互的网络系统。尽管略有差异,但是这些模型都能够通过多种方式进行扩展。有一点可以断言,Actor模型健壮的错误处理策略,使得它对响应性提供的支持称为最强的支持。值得一提的是,尽管这些模型提高系统响应度的方式不同,但所有模型都致力于最大程度地减少阻塞。
响应式系统须遵循的特征
所有可伸缩、可恢复的响应式程序都应遵循这些特征。
消息传递或事件传递
响应式系统必须能对消息或事件进行响应,这是最基本的要求。
可灵活伸缩
为了能够满足处理要求,响应式系统是可伸缩的系统。这意味着该系统能够通过水平扩展的方式进行扩容、调整进程数、处理核数、处理节点数。理想状态下,为了能够动态响应不停变化的处理需求,系统应该根据当前需求动态的执行水平扩展,这种调整既包括增加处理资源,也包括自动回收资源。用这种方法,我们需要花费大量的精力才能对那些需要维护重要状态信息的服务进行横向扩展,而且这类系统也很难对状态信息进行“分片”和可靠的复制。
容错可恢复
随着系统不断变大,那些不常见的事件也会越来越频繁地出现在系统中。因此,错误也是需要考虑的头等大事。构造响应式系统时,必须不断进行改造,以便能够在出现错误时优雅地恢复系统。所以常常需要弱耦合和通用的监督系统的设计。
响应式
响应式系统需要能够随时对服务请求进行响应,即使系统出现了错误的组件或是精力了非常高的流量峰值,响应式也需要通过优雅降级的方式继续响应用户的请求。
总结
本节中给出了响应式编程的基本概念,讨论了响应式系统模型和所遵循的特征。由于该方面的相关资料较为混乱,使得我在学习过程中难以把握一些概念的定界,待日后勤加实践,从Scala的并发系统和akka框架入手,加深对响应式编程的理解。
转载请注明作者Jason Ding及其出处
jasonding.top
Github博客主页(http://blog.jasonding.top/)
CSDN博客(http://blog.csdn.net/jasonding1354)
简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354进入我的博客主页