剖析响应式编程的本质

基于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 条评论
登录 后参与评论

相关文章

来自专栏应兆康的专栏

使用Python进行天气预测之获取数据

所以我们加上了判断语句,当然细心的小伙伴应该可以看到我们这里还会构造出2019年的链接,这个错误链接我们在后面获取数据的时候会进行处理,若链接是没用的,我们选择...

5254
来自专栏张善友的专栏

Microsoft StreamInsight 构建物联网

最近关于“物联网”(IoT) 的争论有很多,而且理由都很充分。 Ericsson 的 CEO Hans Vestberg 预测到 2020 年将有 500 亿台...

1795
来自专栏程序你好

数据库设计中的6个最佳实践步骤

如果设计得当,数据库是记录、存储、检索和比较数据的强大工具。然而,一个没有经过精心设计和目的的数据库不仅仅是无效的,它对那些使用它最多的人(开发人员)来说是一个...

782
来自专栏养码场

一周播报|明明BUG这么多,死也不给看代码?这位程序员你咋这么矫情......

Q:有两张表(一个库),一个是用户表、一个是会员表,一个会员记录对应多条用户记录,有一个事务过程如下:每更新用户表中一条记录,更新(update)对应会员表中的...

682
来自专栏FreeBuf

那些年我们“投(shua)”过的票(续)

*本文原创作者:西毒若相惜,本文属FreeBuf原创奖励计划,未经许可禁止转载 前言 看到上一篇别人写的投(shua)过的票,感觉狗熊所见略同。 上篇的博主好像...

1769
来自专栏腾讯大数据的专栏

腾讯大数据之计算新贵Spark

前言 Spark作为Apache顶级的开源项目,项目主页见http://spark.apache.org。在迭代计算,交互式查询计算以及批量流计算方面都...

1979
来自专栏祝威廉

由CarbonData想到了存储和计算的关系

交代下背景,之前花了半天时间试用了下,主要想解决ElasticSearch历史数据查询的问题,之前出现过在ES上查询一个月数据直接把一些节点跑挂了。然后我打算把...

743
来自专栏码匠的流水账

聊聊系统设计中的trade-off

trade-off翻译过来大致是折中的意思,也就是说系统设计通常牵扯的点比较多,有的设计方案这个方面比较好,但是又有其他缺点,没有十全十美的方案,只是在特定的上...

822
来自专栏前端小吉米

无 Flash 时代,让直播拥抱 H5

1084
来自专栏CSDN技术头条

大规模数据集成: Linked Data

在本系列的前两篇文章(“ 使用 RDF 创建数据网络 ” 和 “ 使用 SPARQL 查询 RDF 数据 ”)中,您了解了资源描述框架和 SPARQL 协议和 ...

1918

扫码关注云+社区