actor模型如何满足现代分布式系统的需求

akka版本2.6.9
版权声明:本文为博主原创文章,未经博主允许不得转载。

 正如在前面的主题中所描述的,常见的编程实践不能正确地满足现代系统的需求。值得庆幸的是,我们不需要放弃我们所知道的一切。相反,actor模型以一种有原则的方式解决了这些缺点,允许系统以一种更好地匹配我们的心智模型的方式运行。角色模型抽象允许您从通信的角度来考虑代码,就像在大型组织中人与人之间进行的交换一样。

 使用actor可以让我们解决如下问题:

  1. 在不使用锁的情况下实施封装。
  2. 使用协作实体对信号做出反应、改变态并相互发送信号的模型来推动整个应用程序向前发展。
  3. 不要担心执行机制与我们的全局不匹配。

消息传递的使用避免了锁定和阻塞
  actor互相发送消息,而不是调用方法。发送消息并不会将执行线程从发送方转移到目的地。actor可以发送消息并在不阻塞的情况下继续。因此,它可以在相同的时间内完成更多的任务。
  对于对象,当方法返回时,它释放对其执行线程的控制。在这方面,actor的行为很像对象,它们对消息做出反应,并在完成当前消息的处理后返回执行。这样,actor实际上实现了我们对对象的计划执行:
在这里插入图片描述
  传递消息和调用方法之间的一个重要区别是消息没有返回值。通过发送消息,参与者将工作委托给另一个参与者。正如我们在调用堆栈的假象中看到的那样,如果它期望返回值,发送actor要么需要阻塞,要么需要在同一线程上执行另一个actor的工作。相反,接收actor以回复消息的形式交付结果。
  我们在模型中需要的第二个关键更改是恢复封装。actor对消息做出反应,就像对象对在其上调用的方法做出“反应”一样。不同之处在于,不同于多个线程“突出”到我们的参与者并破坏内部状态和不变量,参与者独立于消息的发送者执行,并且依次对传入的消息做出反应,一次一个。虽然每个actor按顺序处理发送给它的消息,但不同的actor彼此同时工作,因此actor系统可以同时处理硬件所支持的尽可能多的消息。
  由于每个actor最多只处理一条消息,因此可以在不同步的情况下保持actor的不变量。这是自动发生而不使用锁:
在这里插入图片描述
  总之,当actor收到消息时,会发生以下情况:

  1. actor将消息添加到队列的末尾。
  2. 如果actor没有计划执行,它将被标记为准备执行。
  3. 一个(隐藏的)调度程序实体接受actor并开始执行它。
  4. actor从队列前端获取消息。
  5. actor修改内部状态,向其他actor发送消息。
  6. 这个actor没有安排处理。

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

  • 邮箱(消息在其中结束的队列)。
  • 行为(actor的状态,内部变量等)。
  • 消息(表示信号的数据片段,类似于方法调用及其参数)。
  • 执行环境(接受具有响应消息的actor并调用其消息处理代码的机制)。
  • 一个地址(稍后详细介绍)。

 消息进入actor邮箱。actor的行为描述了actor如何响应消息(比如发送更多消息和/或更改状态)。执行环境编排一个线程池,以完全透明地驱动所有这些操作。

 这是一个非常简单的模型,它解决了前面列举的问题:

  • 封装是通过将执行与信令解耦来保持的(方法调用传输执行,消息传递不传输)。
  • 不需要锁。只能通过消息修改actor的内部状态,在尝试保持不变时,一次处理一个消息以消除竞争。
  • 任何地方都没有使用锁,发送方也没有被阻塞。数百万个actor可以被有效地安排在十几个线程上,从而达到现代cpu的全部潜力。任务委托是actor的自然操作模式。
  • actor的状态是本地的而不是共享的,更改和数据通过消息传播,这映射到现代内存层次结构的实际工作方式。在许多情况下,这意味着只通过包含消息中的数据的高速缓存线进行传输,同时保持本地状态和缓存在原始核心中的数据。相同的模型完全映射到远程通信,其中状态保存在机器的RAM中,更改/数据以包的形式在网络上传播。

actor优雅地处理错误情况
 由于在相互发送消息的actor之间不再有共享的调用堆栈,因此我们需要以不同的方式处理错误情况。我们需要考虑两种误差:

  • 第一种情况是由于任务中的错误(通常是一些验证问题,如不存在的用户ID)导致目标actor上的委托任务失败。在这种情况下,由目标actor封装的服务是完整的,只有任务本身是错误的。服务actor应该用一条消息回复发送者,显示错误情况。这里没有什么特别的,错误是域的一部分,因此成为普通的消息。
  • 第二种情况是服务本身遇到内部错误。Akka强制所有actor被组织成一个类似树的层次结构,即创建另一个actor的actor成为新参与者的父参与者。这与操作系统将进程组织成树的方式非常相似。就像进程一样,当一个actor失败时,它的父actor可以决定如何对失败做出反应。另外,如果父actor被停止,那么它的所有子actor也将被递归停止。这项服务被称为监督,它是Akka的核心。
     管理器策略通常由父actor在启动子actor时定义。它可以决定在某些类型的失败时重启child actor,或者在其他类型的失败时完全停止它。孩子永远不会无声无息地死去(进入无限循环的明显例外),相反,他们要么失败,主管策略可以对错误作出反应,要么停止(在这种情况下,相关方会得到通知)。总是有一个负责管理actor的实体:它的父实体。重新启动从外部是不可见的:当目标actor重新启动时,合作actor可以继续发送消息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值