欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AKKA 学习(三)--- AKKA 2.3 理解 Actor

程序员文章站 2022-05-09 12:14:55
...
      上一节的Actor系统解释了Actor的层次和构建的应用程序的最小单元。本节着眼于单独的一个Actor,解释为了实现它你需要了解的概念。更深入的详细信息,请参阅Actors (Scala)和无类型的Actor(JAVA)(链接暂时缺失)。

      一 个Actor包含状态(State),行为(Behavio),邮箱(Mailbox),子Actor(Children)和监管策略 (Supervisor Strategy)。所有这一切都被封装在一个Actor引用(Actor Reference)中。最后讨论什么时候一个Actor生命结束。

2.3.1 Actor引用(Actor Reference)

      如下所述,为了更好的使用Actor模型,一个Actor对象需要与外部隔离。因此,在外部系统中Actor通过Actor引用暴露,Actor引用是可以*的、不受限制地传递的对象。为了可以传递给所有需要它的操作,它分为内部对象和外部对象:通过一个远程代理代理实际的Actor,这样重启一个Actor不需要更新所有的引用,并且可以在完全不同的应用程序给Actor发生消息。最重要是,在外部不能查看内部Actor的的状态,除非Actor 自己不明智的暴露自身信息。

2.3.2 状态(State)

      Actor 对象通常会包含一些反映其状态的变量,它可能是一个明确的状态机(例如,使用fsm-scala模块),或者是一个计数器,一系列监听器集合,挂起的请求等。这些数据正是一个Actor的价值所在,因此它们必须被保护以免受其他actor损坏。可喜的AKKA的Actor都有自己的轻量级的线程,它与系统的其余部分完全隔离。这意味着你不必使用同步锁来访问,可以只写你自己的Actor代码,而不必担心并发问题。
      在AKKA的背后有一系列的Actor,它们运行在一系列的真实线程上,通常情况下多个Actor共用一个线程,一个Actor的前后两次调用可能运行在不同的线程上。AKKA确保本实现的细节不影响Actor的状态只会同时被单个线程处理。
      由于内部状态对一个Actor是至关重要的,当出现不一致的状态是认为actor失败了。因此,当Actor失败并且通过其监管者重新启动时,这些状态将被重新创建,就好比是第一次创建该Actor。这使的系统有了自我修复的能力。
      或者说一个Actor的状态会自动被覆盖为重启之前的状态息,这通过持久化收到的消息,并且在重启之后重新执行消息来实现(参见持久化)。

2.3.3 行为

      每当处理一个消息的时候,对应当前Actor会有一个行为。行为意味着一个函数,它定义当消息到达时将要采取的一系列的反应,例如一个请求到达,客户端是被授权,还是拒绝它。行为可能随时间而改变,例如:一段时间内不同的客户端需要获得授权,或者由于Actor临时不可用。这些变化可以是通过状态变量中读取 行为逻辑来实现。或者在函数运行时自己被替换移除,例如become和unbecome操作。无论如何,Actor的初始行为定义在actor对象被构造 的过程中,特别注意,Actor重启将会重置其行到初始状态。

2.3.4 邮箱(Mailbox)

      
      有 不同的邮箱实现可供选择,默认是一个FIFO队列:actor处理的消息的顺序和消息到达的顺序一致。这适用与大部分场景,但如果应用程序需要优先处理一 些消息。在这种情况下,一个优先级的邮箱将不会把优先级高的消息排在最后,它甚至可能是最前面的位置。使用这样的队列,处理的消息的顺序会由该队列的算法 决定,而不是一般FIFO。
      一个Actor的目的是处理消息,这些消息是从其他Actor(或从Actor系统外)发送给Actor的。连接发送Actor和接收Actor的部分Actor的邮箱:每个Actor都有一个确切的邮箱来接受所有发件人的消息。这些消息按照发送的时间顺序进入邮箱,这意味着运行时从不同消息发生Actor发送的消息没有明确的顺序,取决于Actor分配线程的随机性。当然,从同一个Actor发送多个消息给同一个目标,它们总是保证相同的顺序。
      在AKKA中有区别其他一些Actor模型的重要的特征:当前行为者必须始终处理下一个出队列的消息,而不会为了匹配下一个消息而遍历邮箱的。除非当前行为被覆盖,否则处理消息失败将被视为出错。

2.3.5  子Actor(Children)

      每个Actor都是一个潜在监管者:如果它创建或者委派的子任务,它会自动监管它们。子Actor的名单维护在它的上下文中,Actor可以访问它们。该列 表的修改可以是创建(context.actorOf(...))或停止(context.stop(child))子Actor,这些操作会同步完成。 而Actor的实际的创建和终止会在后台以异步方式运行,避免阻塞它们的监管者。

2.3.6 监管策略(Supervisor Strategy)

      Actor的最后一块内容是对其子Actor失败之后的处理策略。故障处理在AKKA中是透明地进行的,它通过每一个监管者都带有失败策略并且监控每一个传入失败Actor。这种策略对于以及构建的actor系统是至关重要的,因此一旦创建,不能修改策略。
      考虑对每个Actor来书最终只有一个策略,这意味着,如果一个Acotr的子Actor应用了不同的策略,子Actor会选择最近的监管者的失败策略,这对于Actor系统拆分任务到子任务的机制是非常有利的。

2.3.7  什么时候Actor 消亡

      当 一个Actor消亡,例如:发布失败时没有被重启,自己停止或者它的监管这将他停止,它会释放其占用的资源,并且将其邮箱中的所有剩余的消息插入到系统 的“死亡邮箱”,它们会被作为死亡信件(DeadLetters)转发到事件流(EventStream)中。Actor的邮箱会指向系统邮箱,并且将所 有新邮件作为死亡信件(DeadLetters)转发到事件流(EventStream)中。虽然已经尽最大努力来这样做,但是不要依赖它一定能“保证送 达”。
      为了方便测试,不要默默放过消息:我们可以注册TestEventListener到转发死亡信件的事件总线上,并且为每一个死亡信件到达记录一个警告日志,这对于发生错误时查找问题非常有帮助。可以想象的是,此功能也可以用于其他目的。
相关标签: akka 并发