【问题标题】:Is an ActorRef updated when the associated Actor is restarted by the supervisor?当主管重新启动关联的 Actor 时,ActorRef 是否更新?
【发布时间】:2016-02-11 07:10:30
【问题描述】:

如果我像这样创建一个日志演员

val logger: ActorRef =
    actorSystem.actorOf(Props(new Logger()))

记录器由于异常重新启动,我的记录器停止写入磁盘。

我一直在发消息logger ! msg

我是否正确假设当主管重新启动我的日志演员时 ActorRef 没有更新?

【问题讨论】:

    标签: scala akka akka-supervision akka-actor


    【解决方案1】:

    ActorRef 应该由 Akka 正确更新以指向新的演员实例。 docs 明确指出:

    指向终止actor的引用不等于 指向具有相同路径的另一个(重新创建的)actor 的引用。 请注意,由失败引起的actor重启仍然意味着 它是同一个演员的化身,即 restart 不可见 ActorRef 的消费者

    还有here:

    当 actorOf() 被调用时,它会分配一个演员的化身 由传递到给定路径的 Props 描述。演员化身 由路径和 UID 标识。 重启只会交换 Actor 由 Props 定义的实例,但它是化身,因此是 UID 保持不变。

    当演员停止时,化身的生命周期结束。在 那一点适当的生命周期事件被调用并观察 演员被通知终止。 化身后是 停止,路径可以通过创建一个actor再次重用 演员()。在这种情况下,新化身的名称将是 与上一个相同,但 UID 会有所不同。 ...

    ActorRef 总是代表一个化身(路径和 UID),而不是 只是一个给定的路径。因此,如果一个演员被停止并且一个新的演员 同名的旧化身的 ActorRef 不会被创建 指向新的。

    这是使用ActorRefs 的主要优势之一,否则与演员合作会更加不便。

    您需要检查您的主管策略并确保实际重新启动actor。 默认策略是:

    final val defaultStrategy: SupervisorStrategy = {
      def defaultDecider: Decider = {
        case _: ActorInitializationException ⇒ Stop
        case _: ActorKilledException         ⇒ Stop
        case _: Exception                    ⇒ Restart
      }
      OneForOneStrategy()(defaultDecider)
    }
    

    因此,如果您获得Exception,您的演员将重新启动并且ActorRef 应该是有效的,但是如果您获得其他类型的Throwable,那么它将被停止并且ActorRef 将变得无效。

    【讨论】:

    • 谢谢。这很好地解释了它。我只想补充一点,当一个 Actor 重新启动时,它并没有完成对导致重新启动的消息的处理。在我的例子中,演员从来没有向自己发送消息来触发下一个工作。
    • 感谢@kliew 的跟进。我很好奇它在你的情况下没有按预期工作的原因。
    • 如果你在 Actor System 中,你可以死盯着 ActorRef。但是如果你想从外部维护一个 ActorRef,你会如何保持它是最新的呢?
    猜你喜欢
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2016-04-20
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多