十分钟了解Actor模型

背景

CPU的性能因物理原因不再按照摩尔定律发展了。多核的出现从另外一个角度缓解了计算性能提升的尴尬处境。如果我们要好好利用这些多核的硬件平台资源,则需要使得代码能够并发执行。在使用线程模型开发并发程序的十几年时间中,无数的bug种类的出现使得开发者们束手无策。最终得出结论,线程模型并非构建并发程序的出路。但是不用担心,现在已经有很好的替代品了,接下来我将展示给你们——actor 模型。

The model

Actor模型是一个概念模型,专门用于处理并发计算的。它定义了系统组件该如何表现,以及如何与其他组件交互的一些通用规则。使用Actor模型的最著名的语言莫过于Erlang。接下来,我将主要聚焦在Actor模型本身,而非不同语言中实现的库版本。

 Actors

一个Actor是计算的基本单元,它将接受消息,并基于消息做一些计算工作。该思想与我们经常用到的面向对象语言的思想很类似:一个对象接受消息(方法调用)然后依据消息数据进行计算。主要的不同点在于,actor之间完全独立,没有共享内存。值得注意的是,一个actor维持的私有状态从来不会被其他actor改变,而只会通过接受消息,自己改变自己。

One ant is no ant

一个actor并不能成为actor模型。actor是系统的组件,actor模型认为系统所有的组件都是actor,都有地址,actor通过这些地址进行通信。

Actors have mailboxes

理解这一点很重要,尽管多个actors可以同时执行,但是actor只会顺序处理接收的消息,即每次只处理一个消息。如果想要多个消息同时被处理,则需要将消息分发给多个actors。

消息的发送过程是异步的,不需要actors等待对方接收即可放回继续执行。消息则都被存放在actors维护的邮箱当中。

 

What actors do

当一个actor接收消息时,通常做以下三件事情:

  •  创建更多的actors;
  • 发送消息给其他actors;
  • 指定如何处理接来下的消息。

前两条很直观,是actors模型的特点,但是最后一点就很有意思了。在一个actor维持私有状态之前,第三条基本上意味着定义了接收下条信息之前actor的状态。或者说,actor是如何改变自身状态的。

让我们设想一下,假设一个actor是一个计算器,初始状态为0。当这个actor接收到“+1”的消息后,它将指定接收下一个消息时actor的状态为1,而不是改变原始的状态。

Fault tolerence

Erlang 引入了“任其崩溃”的设计哲学。主要的思想就是不需要保守编程,而是尝试预测所有可能出现的问题并找到方法去解决它。简单的说,不可能在编程的时候顾忌到所有的出错点。Erlang 则提倡“任其崩溃”,但是必须要让这些出现崩溃的代码能够显示地表现出来,让专门负责这块代码的任务知道问题出在哪里。

每段代码都是运行在某个进程(在Erlang中称之为actors)中的。这些进程完全被隔离开来,以为这他们的状态将不会被其他进程影响。我们有一个监管者,仍然是一个进程(Actor),如果有进程崩溃了,监管者将采取相应的措施处理出错的情况。

这使得创建一个“自愈”的系统成为可能,也就是说,及时有actor出现异常并崩溃了,无论什么原因,一个监管者始终能够采取措施使得该actor重回正轨(有很多方法可以做这件事情,最简单直接的方式是重启actor的内部状态)。

 Distribution

Actor模型另外一个有趣的方面是与平台无关,即与平台是否为单节点还是分布式是无关的。想象一下,如果一个ator仅仅是一个邮箱和状态集合的小单元,当它响应消息时,谁会去关心这个actor实际运行在系统的哪个角落?只要我们能够将消息传达给这个actor就行了。这允许我们创建一个可以利用多台计算机的系统,帮助我们从出错中恢复。

 Next steps and other resources

这篇文章只是actor模型的快速理解,有很多语言都是基于actor模型的,例如Erlang,Elixir,以及Akka, Celluloid中的actor库等。

另外还有推荐的额外的参考资料,可供详细了解actor模型:

如果你对actor模型的概念思想感兴趣,我推荐你看这个视频就足够了,插不了视频,附上Youtube链接

以上内容,翻译自:http://www.brianstorti.com/the-actor-model/

为了更好的了解Actor模型的优势,我再次转载了“技术宅男_L”的一篇博客的部分内容。

 The advantages and disadvantages of Actor model

传统的并发编程方式大都使用“锁”的机制,相信大多数都是”悲观锁“,这里几乎可以断定会出现两个明显的问题:

  1. 随着项目体量增大,业务愈加复杂,不可避免大量使用“锁”,然而大家都知道“锁”的机制其实很耗性能的,所以大量使用锁的机制肯定会造成效率不高
  2. 即使大量依赖“锁”解决了系统中资源竞争的情况,但是由于没有一个规范的编程模式,最后系统的稳定性肯定会出问题,最根本的原因是没把系统的任务调度抽象出来,由于任务调度和业务逻辑的耦合在一起,很难做一个很高层的抽象,保证任务调度有序。
  3. 难以维护等等弊端

    上面是传统通过“锁”的机制实现并发编程的缺点,然而Actor为什么一定层度上可以解决这些问题呢?个人认为其最根本的原因是Actor模式下提供了一种可靠的任务调度系统,也就是在原生的线程或者协程级别上做了更高层次的封装。这会给编程模式带来巨大的好处:

  1.   由于抽象了任务调度系统,那么就可以使系统的线程调度可控,易于统一处理,稳定性和可维护性好
  2. 作为开发者我们只需要关心每个Actor的逻辑就可以了,避免“锁”的“滥用”
  3. Actor也提供了很多基本准则,避免了很多并发编程中的问题 

    ……

那么Actor没有缺点吗?那也不是,比如当所有逻辑都跑在Actor中时,很难掌控Actor的粒度,稍有不慎就可能造成系统中Actor个数爆炸的情况,Actor当出现必须共享数据或者状态时就很难避免使用“锁”,但似乎由于上面的“Actor可能会堵塞自己,但Actor不应该堵塞它运行的线程”准则冲突,哈哈,这个时候也许可以选择使用redis做数据共享

有些语言如java,C#并没有原生对Actor模式的支持,但是有很多的开源库弥补了这个缺失。如著名的Akka就提供了对java Actor模式的支持,Akka非常庞大,准确说它不仅是对Actor模式的支持,更是提供了基于Actor编程框架,学习成本其实还蛮高的。推荐一个轻量级基于java的Actor库μJavaActors,它仅仅只有1200行左右的代码,实现了Actor核心,初学者可以把代码读一遍,基本上Actor模式就有个入门了。最后还有一个基于C#的Actor开源项目Orleans,据说被不少大型项目采用。

Last but not least

   μJavaActors简单对Actor有个初步理解,后面会记录一下关于Akka和μJavaActors项目的Demo、源码简单分析,最后会用C#简单实现一个Actor库。下面附上文中提到的技术点的链接:

Orleans,Akka,μJavaActors,Actor入门

转载于:https://my.oschina.net/wanborj/blog/852410

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值