[行业资讯] 聊聊Reactive Programming &Actor模型


最近刚好在infoq上看到下一代分布式的设计理念,感触颇深,二十年来,整个分布式系统架构的演进,从 C/S 到 B/S,再到分布式系统。今天,微服务,网格,云计算大行其道,虽然二十年前我刚刚上初中!

以当前常见的服务架构举例:微服务

以后.png

常见微服务架构,其前端流量入口采用负载。应用层常见是采取一级网络 (通过配置推送的软负载) 或者二级网络 (通过应用网关负载隔离) 模式。阿里是使用前者,百度、新浪使用后者,主要取决于微服务的展现形式 (RPC or Rest-API),差异是是否需要一个专职配置中心。为保证请求无状态地实现迁移,所以使用共享数据节点 (存储各种形式的临时或中间数据) 的形式实现。数据节点往往采用分片的主备模式。

而伴随微服务的增长,当前我们的系统作为2.0基于RPC的微服务架构,也衍生出很多问题,例如服务间调用关系由当初的设计自底向上,逐渐变成网状调用依赖。部署上资源限制,效率瓶颈,缺乏总体架构。大量的远程调用。爆炸式增长的碎片化应用。问题定位变得复。另外,远程调用中最大的问题就是性能问题。

如何解决以上的问题,同时也是下一代架构目标:流式架构/反应式编程(Reactive Architecture/Programming)作为一种范式在整个业界正在逐步受到认可和落地,是对过往系统的业务需求理解梳理之后对系统技术设计/架构模式的提升总结。 作为JAVA程序员的你应该感到高兴,因为,Java作为一个成熟平台,对于趋势一向有些稳健的接纳和跟进能力,有着令人惊叹的生命活力: 
   1.
Java 7提供了ForkJoinPool,支持了Java 8提供的Stream(Reactive Stream是RP的一个核心组件)。 
   2. 另外Java 8还提供了Lamda(有效地表达和使用RP需要FP的语言构件和理念)。 
   3. 有了前面的这些稳健但不失时机的准备,在Java 9中提供了面向RP的Flow API,为Java圈子提供了官方的RP API,标志着RP由集市式的自由探索阶段 向 教堂式的统一使用的转变。 

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

  说了这么就,什么是响应式编程(Reactive Programming)?传统的顺序编程采用每条指令依次执行的方式,上一条指令没有执行结束,当前的线程就得等着,任你如何提升机器性能还是代码性能,如果本质不变,始终改变不了响应需要等待的现实。若要响应迅速,就得把顺序执行指令的方式换一换——同步换成异步,方法执行换做消息发送,于是,就有了上边的响应式的定义:响应式编程就是异步数据流编程,这其实是一种编程范式,是编程理念的一种思想转型。因为采用响应式编程,我们就不再将软件要处理的业务视为对象,又或者函数,而是直接透析到本质:数据流(Data Stream)。

万事万物皆为流

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

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

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

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

  • 保持数据的不变性

  • 没有共享

  • 阻塞是有害的

恰好,这三条特征也是Actor模型拥有的。

Actor,这个诞生在1970的产物,遥遥领先于那个时间,知道很久以后,Erlang这种基于Acotr的模型设计的面向并发编程的新语言横空出世,并在并发领域树立一座丰碑,古老的Actor才重见天日,再次成为分布式计算领域的焦点技术之一,目前,几乎所有的主流平台都支持Actor模型:JAVA平台下的Scala的Actor类库jetlan。

Actor的理念很简单,Actor是一等公民,一切皆Actor,之间通过消息发送通信,所有都是异步的,不同Actor可以自己处理各自的消息。整个系统获得良好的大规模并发处理能力。

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

Actor系统模仿了人类的组织,如公司、政府和其他大型机构。在软件公司中,有许多需要以并发方式达成的目标。为了实现这些目标,数百或数千名员工一起努力工作,而且这些员工通常会被组织成一种层次结构。许多员工会为级别比他们低的员工分派工作。为了高效地工作和决策,员工们使用电子邮件进行通信。

当员工早上上班时,就会检查他的电子邮箱并对重要的消息做出回应。如果某封电子邮件非常重要,那么这个员工就必须立刻回复这封邮件。当员工忙着回复一封电子邮件时,可能会收到另一封电子邮件,而且后续的电子邮件都会进入他的电子邮箱中。只有当员工处理完成当前的电子邮件后,他才能继续处理下一封电子邮件。

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

因而对于每个Actor而言:

  • 每个Actor都拥有独立的MailBox;

  • 接收到的消息皆为不可变对象,且完全独立;

  • 不管是tell消息还是ask消息,Actor执行消息的方式都是异步非阻塞的。

不得不提的Akka

 AKKA框架是一个实现Actors模型的Scala或Java平台,实现多线程安全应用。

  Actors是一个轻量级的对象,通过发送消息实现交互。每个Actors在同一时间处理最多一个消息,可以发送消息给其他Actors。在同一时间可以于一个Java虚拟机存在数以百万计的参与者,构架是一个分层的父层(管理) - 子层,其中父层监控子层的行为。还可以很容易地扩展Actor运行在集群中各个节点之间 - 无需修改一行代码。每个演员都可以有内部状态(字段/变量) ,但通信只能通过消息传递,不会有共享数据结构(计数器,队列) 。Akka框架支持两种语言Java和Scala,

** is cheap,show me the code

Akka actors是轻量,能够平均在一个系统创建数千个。线程是重量的,场景切换相当慢。横向扩展Scale out,Actor能够在代码没有任何修改时在远程运行。失败恢复和错误处理

ActorJava代码

1.png

2.png

3.png

4.png

就如上面简介中所说的,AKKA把并发操作的各种复杂的东西都统一的做了封装.我们主要关心的是业务逻辑的实现,只需要少量的关心Actor模型的串联即可构建出高可用,高性能,高扩展的应用.

我希望在后续的应用的开发中朝着这个方向努力,今天的分享就到这里。最近我对内存相关的内容比较感兴趣,下个blog我会在跟大家分享下关于内存的内容。

谢谢!

  

部分资料来自 infoq & 简书

https://www.jianshu.com/p/3bdb8dbaa35c