【问题标题】:Akka - how a parent sends a message to child after child had an exceptionAkka - 在孩子发生异常后父母如何向孩子发送消息
【发布时间】:2017-08-17 09:48:47
【问题描述】:

假设我有一个 parent 演员,它一次向其 child 演员发送一条消息

当子进程完成当前消息的处理后,它会通知父进程轮流向子进程发送一条新消息。

为了即使孩子在某个消息上崩溃也能保持这个循环,我向父级添加了一个 SupervisorStrategy :

    private static SupervisorStrategy strategy =
        new OneForOneStrategy(10, Duration.create("1 minute"),
                new Function<Throwable, SupervisorStrategy.Directive>() {
                    @Override
                    public SupervisorStrategy.Directive apply(Throwable t) {
                        if (t instanceof NullPointerException) {
                            return resume();
                        } else {
                            return escalate();
                        }
                    }
                });

这个想法是,无论孩子发生什么,它都会恢复,并且父母将能够向它发送下一条消息。

但是父级如何知道错误何时发生,以便发送下一条消息?

对于父母来说孩子发生了什么事的触发因素是什么?

我需要重写类似“onChileError”的方法吗?

(将应用 Java over Scala 示例)

谢谢。

【问题讨论】:

    标签: java akka akka-supervision


    【解决方案1】:

    当子进程处理完当前消息后,它会通知父进程它会向子进程发送一条新消息....

    这个想法是,无论孩子发生什么,它都会恢复,并且父母将能够向它发送下一条消息。

    您当前的主管策略执行以下操作:如果将 NullPointerException 扔给子级,则子级将恢复,就好像什么都没发生一样。如果抛出一个不同的异常,它会在actor层次结构中进一步升级,这可能意味着default supervisor strategy 启动,在这种情况下,子进程会重新启动。如果您希望孩子不管异常情况都恢复,请将您的策略​​更改为以下(我使用的是DeciderBuilder):

    private static SupervisorStrategy strategy =
      new OneForOneStrategy(10, Duration.create(1, TimeUnit.MINUTES), DeciderBuilder.
        match(Exception.class, e -> {
          // getSelf() is the parent and getSender() is the child
          GiveMeAnotherMessage message = // ...
          getSelf().tell(message, getSender());
          resume();
        })
        .matchAny(o -> escalate())
        .build());
    
    @Override
    public SupervisorStrategy supervisorStrategy() {
      return strategy;
    }
    

    但是父级如何知道错误发生的时间,以便发送下一条消息?

    孩子发生了什么事,父母的触发因素是什么?

    我需要重写类似“onChileError”的方法吗?

    决策者可以通过getSender() 访问当前失败子节点的引用,因此您只需向父节点发送一条消息,让其知道子节点已准备好从内部处理另一条消息策略本身,如上面的代码所示。

    【讨论】:

      【解决方案2】:

      我建议实现下一个场景(示例在 Scala 中):

      配置主管策略以停止错误

      // Stop actors on error - DeathWatch will handle restart sequence
      override def supervisorStrategy: SupervisorStrategy = SupervisorStrategy.stoppingStrategy
      

      订阅儿童死亡守望的创作

      def createWorker() = {
        val worker = actorOf(...)
        context.watch(worker)
        worker
      }
      

      如果孩子意外终止,请创建一个新的并重新发送当前要完成的部分工作(或下一个,如果合适的话)

      case Terminated(actor) => 
        val worker = createWorker()
        worker ! DoWork(...)
      

      一旦您开始在集群中扩展参与者,这也将有所帮助,因为当节点在集群中变得不可访问时,它不会触发监督策略,只会触发远程死亡监视。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-14
        • 1970-01-01
        • 1970-01-01
        • 2022-08-03
        • 1970-01-01
        • 1970-01-01
        • 2022-11-15
        相关资源
        最近更新 更多