• [面试]Actor模型


    Actor模型

    面试中自己说话不利落, 或者自己对知识点认识不全面.在这里进行一下记录. 理论部分都是收集(copy)自网上其他的博客.

    什么是Actor模型

    参与者模式英语:Actor model)是一种并发运算上的模型。

    “参与者”是一种抽象概念,被视为并发运算的基本单元:当一个参与者接收到一则消息,它可以做出一些决策、创建更多的参与者、发送更多的消息、决定要如何回答接下来的消息。Actor模型的理念非常简单:天下万物皆为Actor。

    在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改). 

    Actor模型的组成是什么

            1.状态(state):Actor中的状态指的是Actor对象的变量信息,状态由Actor自己管理,避免了并发环境下的锁和内存原子性等问题

            2.行为(Behavior):行为指定的是Actor中计算逻辑,通过Actor接收到消息来改变Actor的状态

            3.邮箱(mailBox):邮箱是Actor和Actor之间的通信桥梁,邮箱内部通过FIFO消息队列来存储发送方Actor消息,接受方Actor从邮箱队列中获取消息. 

    为什么同一个功能的Actor会有多个实例

    尽管许多actors同时运行,但是一个actor只能顺序地处理消息。也就是说其它actors发送了三条消息给一个actor,这个actor只能一次处理一条。所以如果你要并行处理3条消息,你需要把这条消息发给3个actors。

    消息异步地传送到actor,所以当actor正在处理消息时,新来的消息应该存储到别的地方。Mailbox就是这些消息存储的地方。

    Actor做什么

    当一个actor接收到消息后,它能做如下三件事中的一件:

             1. Create more actors; 创建其他actors

             2. Send messages to other actors; 向其他actors发送消息

             3. Designates what to do with the next message. 指定下一条消息到来的行为

    一个actor能维持一个私有状态。「指定下一条消息来到做什么」意味着可以定义下条消息来到时的状态。

    设想有一个actor像计算器,它的初始状态是数字0。当这个actor接收到add(1)消息时,它并不改变它原本的状态,而是指定当它接收到下一个消息时,状态会变为1。

    Actor模型的优点

            1. 事件模型驱动--Actor之间的通信是异步的,即使Actor在发送消息后也无需阻塞或者等待就能够处理其他事情

            2. 强隔离性--Actor中的方法不能由外部直接调用,所有的一切都通过消息传递进行的,从而避免了Actor之间的数据共享,想要观察到另一个Actor的状态变化只能通过消息传递进行询问. 

            3. 位置透明--无论Actor地址是在本地还是在远程机上对于代码来说都是一样的

            4. 轻量性--Actor是非常轻量的计算元,只需少量内存就能达到高并发

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

            6.作为开发者我们只需要关心每个Actor的逻辑就可以了,避免“锁”的“滥用”

    Actor缺点

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

    Actor模型的调度方式

    Actor模型有两种任务调度方式:

            1. 基于线程的调度:为每个Actor分配一个线程,在接收一个消息时,如果当前Actor的邮箱(mail box)为空,则会阻塞当前线程。基于线程的调度实现较为简单,但线程数量受到操作的限制,现在的Actor模型一般不采用这种方式;

            2. 基于事件的调度:事件可以理解为上述任务或消息的到来,而此时才会为Actor的任务分配线程并执行。

    基于线程的调度为每个Actor分配一个线程,在接受一个消息(如在Scala Actor中使用receive)时,如果当前Actor的“邮箱(mail box)”为空,则会阻塞当前线程直到获得消息为止。基于线程的调度实现起来较为简单. 但是线程数量一多就会影响到系统资源占用以及调度,而在某些情况下大部分的Actor会处于空闲状态,而大量阻塞线程既是系统的负担,也是资源的浪费。因此现有的Actor Model大都不会采取这种方式。

    基于事件的调度中, “事件”在这里可以简单理解为“消息到达”事件,而此时才会为Actor的任务分配线程并执行, 既保证了运算资源的充分占用,也不会让系统在同时进行的太多任务中“疲惫不堪”,这样系统便可以得到很好的伸缩性。在Scala Actor中也可以选择使用“react”而不是“recive”方法来使用基于事件的方式来执行任务。

    Actor的容错(Fault tolerance)

    Erlang 引入了「随它崩溃」的哲学理念,这部分关键代码被监控着,监控者的唯一职责是知道代码崩溃后干什么(如将这个单元代码重置为正常状态),让这种理念成为可能的正是actor模型。

    每段代码都运行在process中,process是erlang称呼actor的方式。这个process完全独立,意味着它的状态不会影响其他process。我们有个supervisor,实际上它只是另一个process(所有东西都是actor),当被监控的process挂了,supervisor这个process会被通知并对此进行处理。这就让我们能创建「自愈」系统了。如果一个actor到达异常状态并崩溃,无论如何,supervisor都可以做出反应并尝试把它变成一致状态,这里有很多策略,最常见的是根据初始状态重启actor。

    Actor与分布式的关系

    关于actor模型的有趣方面是它并不在意消息发送到的actor是本地的或者是另外节点上的。

    转念一想,如果actor只是一些代码,包含了一个mailbox和一个内部状态,actor只对消息做出响应,谁会关注它运行在哪个机器上呢?只要我们能让消息到达就行了。这允许我们基于许多计算机上构建系统,并且恢复其中任何一台。

    用WordCount举例

    比如现在要在3台物理节点上运行一个WordCount作业,可以将这个作业细分为Split、Count和Merge三种任务(任务的target是物理节点的地址,communication可能包含文本、单词及计数等),根据需求要有Split Actor、Count Actor和Merge Actor。整个作业的处理流程以下:

            1. Split Actor接收到消息后可以文本分割成10份,每份发送给一个Count Actor;

            2. Count Actor统计好单词的数目后发送消息给Merge Actor;

            3. Merge Actor收集完Count Actor发送的10个消息后,合并每个单词的数目,完成WordCount任务。

    从以上例子可以看出,Actor系统跟数据驱动系统比如数据流相近,可以自定义任务的流向及其处理过程。

    参考博客(就是copy+整理):

    https://blog.csdn.net/gulianchao/article/details/7249117

     https://www.cnblogs.com/lixiang-share/p/5829437.html

  • 相关阅读:
    随笔2
    随笔
    关于updateElement接口
    随笔1
    本地访问正常,服务器访问乱码 记录
    Redis (error) NOAUTH Authentication required.解决方法
    tomcat启动很慢 停留在 At least one JAR was scanned for TLDs yet contained no TLDs.
    微信公众号消息回复
    微信公众号 报token验证失败
    idea中web.xml报错 Servlet should have a mapping
  • 原文地址:https://www.cnblogs.com/noKing/p/9187362.html
Copyright © 2020-2023  润新知