剖析响应式编程的本质

基于Actor的响应式编程计划分为三部分,第一部分剖析响应式编程的本质思想,为大家介绍何谓响应式编程(Reactive Programming)。第二部分则结合两个案例来讲解如何在AKKA中实现响应式编程。第三部分则是这个主题的扩展,在介绍Reactive Manifesto的同时,介绍进行响应式编程更为主流的ReactiveX框架。

响应式编程(Reactive Programming)到底是什么?从名词定义来讲,中文的响应式并没有很好地展现Reactive的本意。响应这个词语是一个中性词,本身没有任何倾向。Reactive Programming强调的是“响应迅速”,响应用户的请求要如电光火石一般迅捷,做到一触即发。

传统的顺序编程采用每条指令依次执行的方式,倘若上一条指令没有执行结束,当前的线程就得等着,任你如何提升机器性能还是代码性能,如果本质不变,始终改变不了响应需要等待的现实。若要响应迅速,就得把顺序执行指令的方式换一换——同步换成异步,方法执行换做消息发送,于是乎,我们可以精简地定义:

响应式编程就是异步数据流编程。

这其实是一种编程范式,是编程理念的一种思想转型。因为采用响应式编程,我们就不再将软件要处理的业务视为对象,又或者函数,而是直接透析到本质:数据流(Data Stream)。

一言以蔽之:万事万物皆为流。

我这么说,可能有些绝对。响应式编程并非银弹,也非你手中四处寻找钉子来敲打的锤子。我们须得结合着实际的场景,考虑是否选择响应式编程这种范式。然而,如果我们局限在响应式编程的语境下,我们确乎可以视万事万物为流。

从函数式编程的角度来讲,一连串组合函数的调用,其实就是数据在流动。函数可以抽象地视为一种数据类型到另一种数据类型的转换。将各种形式的转换(map、flatMap、filter)穿起来,同时保证数据的不变性(Immutable),则数据就能非常可靠地在函数链条中流动,或者被分析,或者被转换,或者被过滤。

回到业务世界。我们几乎可以将所有业务处理流程都可以建模为数据流的形式。这种流动差不多可以归纳为:

Command -> CommandHandler -> Event -> EventHandler -> Command ...

这是一种颇有节奏感的“建模仪式”。按照CQRS的设计思想,任何业务都可以分解为两种形式的消息:Query与Command。Query模型相对简单,因为它本质上就是一个没有副作用的只读操作。执行Command本身是要改变业务对象值的,然而,如果我们将每次变更都视为是一种“状态的迁移”,然后利用事件去记录每次变更,就可以将可变转换为不变。如果熟悉git,就会发现git的版本管理与此建模思想不谋而合。无论是新增、修改还是删除代码,都可以视为是一次全新的提交。

当我们将编程的范式切换为“流(Stream)”时,我们欣喜地发现,这种方式可以在很大程度上确保数据是不变的。这就为并行开发创造了可能。

然而,普通的数据流编程范式并不能满足“响应式Reactive”的本初定义。我们需要响应迅速。如何才能做到?那就是要做到没有阻塞,这就是我们通常所说的异步工作方式。

因而,响应式编程的设计原则是:

  • 保持数据的不变性
  • 没有共享
  • 阻塞是有害的

这或许也可以视为是响应式编程的特征,恰好,这三条特征也是Actor模型拥有的。

那么,什么是Actor模型?溯源Actor模型,它由Carl Hewitt在1973年提出,之后在Erlang OTP(Open Telecom Platform)中被广泛应用在并发编程上。最初的Scala语言也实现了简单的Actor模型,但随着AKKA框架的推出,Scala放弃了自身的Actor,转而选择使用AKKA。

在《Scala并发编程》一书中,Aleksandar Prokopec形象地描述了Actor系统:

Actor系统模仿了人类的组织,如公司、政府和其他大型机构。在软件公司中,有许多需要以并发方式达成的目标。为了实现这些目标,数百或数千名员工一起努力工作,而且这些员工通常会被组织成一种层次结构。许多员工会为级别比他们低的员工分派工作。为了高效地工作和决策,员工们使用电子邮件进行通信。 当员工早上上班时,就会检查他的电子邮箱并对重要的消息做出回应。如果某封电子邮件非常重要,那么这个员工就必须立刻回复这封邮件。当员工忙着回复一封电子邮件时,可能会收到另一封电子邮件,而且后续的电子邮件都会进入他的电子邮箱中。只有当员工处理完成当前的电子邮件后,他才能继续处理下一封电子邮件。

在这个隐喻中,软件公司就相当于是一个ActorSystem,每位员工则是一个一个Actor。电子邮件是Actor之间彼此发送的消息(Message),一旦发送了消息,就不必等待收件人的回复,可以继续自己的工作,也就是说这种消息发送的方式是异步非阻塞的。Actor持有的MailBox正好借用了这里所谓的电子邮箱概念。

因而对于每个Actor而言:

  • 每个Actor都拥有独立的MailBox;
  • 接收到的消息皆为不可变对象,且完全独立;
  • 不管是tell消息还是ask消息,Actor执行消息的方式都是异步非阻塞的。

金风玉露一相逢,从某种意义上讲,Actor模型就是响应式编程苦苦追寻的良缘佳配。二者天生匹配,且Actor模型的分布式特性还能更好地加强响应式编程的响应与处理速度。

原文发布于微信公众号 - 逸言(YiYan_OneWord)

原文发表时间:2016-09-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏進无尽的文章

视频直播| 基础原理篇

912
来自专栏Golang语言社区

从架构的角度看如何写好代码

软件架构实际上包括了:代码架构,以及承载代码运行的硬件部署架构。实际上,硬件部署架构最终还是由代码的架构来决定。因为代码架构不合理,是无法把一个运行单元分拆出多...

26110
来自专栏架构师之路

互联网公司研发RD如何撰写总体设计与详细设计文档

研发工程师(RD)需要撰写的设计文档主要分为:总体设计文档 + 详细设计文档,后简称为“总设”+“详设”。 总设和详设都应该包含的部分: (1) 需求:一般以产...

4277
来自专栏大数据和云计算技术

大数据和云计算技术周报(第44期):NoSQL特辑

https://mp.weixin.qq.com/s/TdnZeG8rRYwTfopEyTxmpQ

671
来自专栏JAVA烂猪皮

淘宝面试回来,想对程序员们谈谈

因为我是一个不管做什么事情都喜欢进行总结的一个人。所以对于在上周去淘宝面试的经历,现在面试回来总结,我想对所有程序员们谈谈。

853
来自专栏LET

CPU简介

1659
来自专栏熊二哥

考试备战系列--软考--01基础架构概念

由于一些知识性的特殊需要,要求掌握比较过时的软件架构设计理论,因而作此文案用于记忆和查询。该部分内容与现实中软件开发相去甚远,也可以理解一些东西之间确实存在很大...

1676
来自专栏微信公众号:Java团长

以技术面试官的经验分享毕业生和初级程序员通过面试的技巧(Java后端方向)

本来想分享毕业生和初级程序员如何进大公司的经验,但后来一想,人各有志,有程序员或许想进成长型或创业型公司或其它类型的公司,所以就干脆来分享些提升技能和通过面试的...

371
来自专栏鸿的学习笔记

《design data-intensive application》阅读笔记之一

于2017年末得知了一本神书《design data-intensive application》,读完即可惜,如果早拿到这本书,就不会纠结于很多分布式系统...

572
来自专栏编程一生

离线数据推送问题(消息队列)

1032

扫描关注云+社区