Actor模型满足现代分布式系统的需求

      官方链接

        通常的编程实践不能够正确的解决现代系统的需求.幸运的是,我们不需要丢弃掉我们知道的所有事.反之,Actor模型用有原则的方法解决这些缺点,使我们系统更匹配我们想要的模型. Actor模型抽象允许我们通过通信的角度去思考我们的代码,这个和人们在大的组织出现交换没有什么不同.

使用Actor 我们可以:

  • 在不使用锁的情况下使用封装
  • 使用实体协作的模型对信号做出反应,改变状态并且发送信号给其他的Actor 来推进整个应用向前
  • 不再担心执行机制不匹配我们以有的经验

通过使用消息避免锁和阻塞

      和方法调用不同,actor之间通过发送消息给彼此.发送消息不会把执行的线程从发送者传递到目的地.一个Actor可以发从一个消息并且无阻塞的继续工作.因此,可以在同样的时间内完成更多的工作.

      对于对象,当一个方法返回,它将释放对于执行线程的控制.对于这点,actor也如同对象一样.当他们他们完成处理当前消息后,对消息作出反应并且返回执行.使用这个方法,actor实际上完成了我们想象中对象的执行:

没有返回值,是传递消息和方法调用的区别.通过传递消息,一个actor把工作委托给另一个actor.对于调用堆栈,如果期望一个返回值,发送的动作需要阻塞或者执行在同一个线程其他actor的工作.而actor模型则是通过返回消息来传递结果.

    第二个我们需要的关键改变是在我们的模型中恢复封装(reinstate encapsulation).Actor对于消息的响应和对象调用方法类似,不同点是取代了多线程对于我们actor的侵入和破坏内部状态以及不可变性,Actor是从消息这发送独立执行的,他们按照顺序响应消息,一个时间处理一个消息.当每个actor按照发送给他们的顺序处理消息时,不同的actor之间可以并行得工作,这样一个Actor系统就可以在硬件提供的基础上尽可能多的处理消息.

    因为一个消息总是被一个Actor处理,一个Actor的不可变性就能不在同步的情况下被保持,这些事在不使用锁的情况下自动发生的:

概述一个actor接受了消息时发生什么:

  1. actor把消息添加到队列尾部
  2. 如果一个actor没有为执行规划,它会被标记为准备去执行(ready to execute)
  3. 一个隐藏的调度者实体获取了Actor并且开始执行actor
  4. Actor从队列末端获取到消息
  5. Actor修改内部状态,发送消息给别的actor
  6. Actor变为未调度(unscheduled)

为了完成这些行为,actor有:

  • 一个邮箱(一个消息从末端进入的队列)
  • 一个行为(actor的状态,内部变量等)
  • 消息(代表一个信号的数据块,如同方法调用和参数)
  • 一个执行环境(这个机制使actor有消息可以响应并且调用他们消息处理的代码)
  • 一个地址

消息发送给actor的邮箱.actor的行为描述了actor如果回应这些消息(比如发送更多的消息或者改变状态).一个执行环境编排了一个线程池去透明的驱动所有的动作完成.

这是个简单的模型并且解决了前面列举的问题:

封装被保留下来,通过信号的传递解耦了执行的程序(方法调用传递执行,消息传递没有).

不需要锁.修改一个actor的内部状态只能通过发送消息实现,同一时间处理一个当试图保持不变性的时候消息消除了竞争.

再也不用使用锁了,发送者也是非阻塞的.百万个Actor可以高效的被调度在十几个线程中,发挥了CPU的全部潜能.任务委托对于actor来说是一个常用的的操作模型.

actor的状态事本地的并且共享,改变数据是通过传递消息,这些消息映射到当代内存层次结构的实际工作方式.在许多方面,这意味着数据的传输仅仅只有包含数据的缓存行,在原始和心中保持状态和数据缓存.同样的模型可以映射到远程通信,状态保持在一个机器的RAM中,改变或者数据在网络上如同包一样被传播.

Actor优雅的处理异常情况

我们已经不通过在actors之间共享堆栈来调用而是彼此之间发送消息,我们需要使用不同的方式处理异常场景.又两种我们需要考虑的错误场景:

  1. 当委托的任务在目标actor犹如一个任务的错误失败了(比如校验失败).对于这个,目标的actor的服务是没问题的,只是任务自身出现问题.服务的actor应该给发送者发送一个消息,代表这个错误的.这里没有什么特别,错误是领域的一部分,因为它变成了一个普通的消息
  2. 当一个服务自身出现了內部错误.Akk强制所有的actor被组织在一个树状的层次中,比如,一个actor创建了另一个actor则它变成了新的Actor的父actor.这个和操作系统把进程组织成一个棵树很像.和进程一样,当一个actor失败了,他的父actor决定怎么响应这个错误.同样当父actor被停止了,他的所有子actor将递归的被停止.这个服务被叫做 监督(supervision),它是Akka的核心

Supervisor 一个监督策略当开启一个子actor时明确的被父actor定义.它可以决定在一些类型的错误上是重启还是停止子任务.子actor从来不会默默挂掉(除非进入了死循环),他们妖魔失败被监管者处理这些失败,或者他们被停止(这种情况下会通知相关部分).总会有个负责的实体来管理actor:它的父actor.重启对外是不可见的,合作的actor仍然可以在重启的过程中给Actor发送消息.

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FantasyBaby

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值