Akka中Actor介绍《seventeen》译

What is an Actor?

上一节关于Actor Systems的部分解释了actor如何形成层次结构,并且是构建应用程序时的最小单元。本节将单独查看一个这样的actor,解释在实现它时的概念。有关所有细节的更深入参考,请参阅Actors

Actor是State,Behavior,Mailbox,Child Actors和Supervisor Strategy的容器。所有这些都封装在Actor Reference之后。一个值得注意的方面是演员有一个明确的生命周期,当不再被引用时它们不会被自动销毁;在创建一个之后,您有责任确保它最终也会被终止 - 这也可以控制当Actor终止时如何释放资源。

Actor Reference

如下所述,需要从外部屏蔽actor对象以便从actor模型中受益。因此,使用actor Reference将actor表示到外部使用,actor Reference是可以自由且无限制地传递的对象。这分为内部和外部对象,可以实现所有所需操作的透明性:重新启动actor而无需在其他地方更新引用,将实际的actor对象放在远程主机上,向完全不同的应用程序中的actor发送消息。但最重要的方面是,除非演员本身不明智地发布这些信息,否则无法查看演员内部并从外部获取其状态。

State

Actor对象通常包含一些反映actor可能处于的状态的变量。这可以是显式状态机(例如使用FSM模块),也可以是计数器,监听器集,待处理请求等。这些数据是让演员有价值的东西,必须保护他们免受其他演员的腐败。好消息是,Akka Actor在概念上每个都有自己的轻量级线程,完全屏蔽了系统的其他部分。这意味着您不必使用锁来同步访问,而是可以编写您的actor代码而不必担心并发性。

在幕后,Akka将在一组真实线程上运行多组actor,通常许多actor共享一个线程,并且一个actor的后续调用最终可能会在不同的线程上进行处理。Akka确保此实现细节不会影响处理actor状态的单线程。

因为内部状态对于Actor的操作至关重要,所以具有不一致的状态是致命的。因此,当actor失败并由其主管重新启动时,将从头开始创建状态,就像首次创建actor一样。这是为了实现系统自我修复的能力。

通过持久保存收到的消息并在重新启动后重放它们,可以自动将actor的状态恢复到重启前的状态(请参阅“ Persistence”)。

Behavior

每次处理消息时,都会根据actor的当前behavior进行匹配。behavior是指定义在该时间点对消息作出反应的动作的函数,例如,如果客户端被授权则转发请求,否则拒绝它。此行为可能会随时间而改变,例如因为不同的客户端会随着时间的推移获得授权,或者因为参与者可能会进入“服务中断”模式并稍后返回。这些更改是通过在状态变量中对它们进行编码来实现的,这些状态变量是从行为逻辑中读取的,或者函数本身可以在运行时被换出,请参阅变为和不成熟的操作。但是,在构造actor对象期间定义的初始行为是特殊的,因为重新启动actor会将其行为重置为此初始行为。

Mailbox

Actor的目的是处理消息,这些消息从其它Actor(或Actor系统外部)发送。连接发送者和接收者的片段是Actor的邮箱:每个Actor只有一个邮箱,所有发件人都将其邮件排入队列。入队以发送操作的时间顺序发生,这意味着由于跨线程分配actor的明显随机性,从不同的actor发送的消息可能在运行时没有定义的顺序。另一方面,从同一个actor向同一目标发送多个消息将以相同的顺序排列它们。

有不同的邮箱实现可供选择,默认为FIFO:由actor处理的消息的顺序与它们排队的顺序相匹配。这通常是一个很好的默认设置,但应用程序可能需要优先处理某些消息而不是其他消息。在这种情况下,优先级邮箱不会总是排在最后,而是排列在消息优先级给定的位置,甚至可能位于前面。在使用这样的队列时,处理的消息的顺序自然会由队列的算法定义,并且通常不是FIFO。

Akka与其他一些actor模型实现的不同之处在于,当前行为必须始终处理下一个出列的消息,没有扫描邮箱以查找下一个匹配的消息。无法处理消息通常会被视为失败,除非覆盖此行为。

Child Actors

每个Actor都可能是一个主管:如果它创建子任务来委派子任务,它将自动监督它们。子项列表保存在actor的上下文中,并且actor可以访问它。通过创建(context.actorOf(...))或停止(context.stop(child))子项来完成对列表的修改,并立即反映这些操作。实际的创建和终止操作以异步方式在幕后发生,因此它们不会“阻止”他们的主管。

Supervisor Strategy

Actor的最后一部分是处理其子女故障的策略。然后,Akka透明地完成故障处理,对每个进入的故障应用监督和监控中描述的策略之一。由于此策略是Actor系统结构的基础,因此一旦创建了Actor,就无法更改。

考虑到每个Actor只有一个这样的策略,这意味着如果不同的策略适用于一个Actor的各个孩子,那么这些孩子应该被分组在具有匹配策略的中间监督者之下,再次优先考虑Actor系统的结构。将任务拆分为子任务。

When an Actor Terminates

一旦一个actor终止,自行停止或被其主管停止,它将释放其资源,将所有剩余的消息从其邮箱中排放到系统的“死信邮箱”中。将它们作为DeadLetters转发到EventStream。然后,使用系统邮箱在actor引用中替换邮箱,将所有新消息重定向到EventStream作为DeadLetters。尽管如此,这是在尽力而为的基础上完成的,因此不要依赖它来构建“保证交付”。

不仅仅是默默地转储消息的原因受到了我们的测试的启发:我们在转发死信的事件总线上注册了TestEventListener,并且会在收到的每封死信中记录警告 - 这对解密很有帮助更快地测试失败。可以想到,该特征也可用于其他目的。

猜你喜欢

转载自my.oschina.net/u/2277632/blog/2908180