当前位置: 首页 > 知识库问答 >
问题:

Akka中的错误内核和监督:来自陈旧儿童的消息会被传递给重启的演员吗?

景帅
2023-03-14

如果一个行动者携带非常重要的数据(即如果可以避免,其状态不应丢失),该行动者应将任何可能危险的子任务提供给它所监督的儿童,并酌情处理这些儿童的失败。根据请求的性质,最好为每个请求创建一个新的子请求,这样可以简化收集答复的状态管理。这被称为Erlang的“错误内核模式”。

...创建子级并将容易出错的工作委托给它们是一个好主意,将重要的状态集中在父级/主管角色中。

在这个场景中,如果具有重要状态的actor由于某种原因重新启动,我是否需要处理来自它的陈旧子级(在重新启动之前创建的)的消息?

CB的构造函数中创建。

然后假设消息BCB发送到CC开始处理它(让我们想象一下它在那里运行长时间运行的计算),一旦完成,将用CB回复B

现在,假设在将CB发送到B并由B处理之前,A将消息AB发送到B。此消息导致b抛出异常,并且作为a监督策略决策的结果,b将重新启动。

重新启动的b会从c接收在b重新启动之前发送的cb吗?

如果是,那么CB(C)的发件人是否被视为重新启动B的子级?CC'的actor ref是否相等(假设CC'的名称相等)?

共有1个答案

后安民
2023-03-14

是的,重新启动的B将从第一个C收到响应。如果C正在执行长时间运行的工作,而其父级失败,则在C完成长时间运行的工作之前,B实际上不会重新启动。作为重新启动b的一部分,将停止(不是重新启动)原始的c,并创建一个新的c(您称之为c'),它是重新启动的b的子级。但是,第一个C将不是重新启动的B的子级。

当第一个C完成时,其发件人引用仍然有效,即使该响应即将重新启动,该响应仍然可以传递到该refs邮箱。当重新启动b时,它能够保留重新启动前邮箱中的内容,从而在启动备份后立即接收并处理cb消息。

我起草了一个小代码示例来展示这种行为:

import akka.actor._
import concurrent.duration._

object RestartExample extends App{
  case object Start
  case object AB
  case object BC
  case object CB

  val system = ActorSystem("test")
  val a = system.actorOf(Props[A])
  a ! Start

  class A extends Actor{
    val b = context.actorOf(Props[B], "myb")
    import context.dispatcher

    def receive = {
      case Start =>
        b ! Start
        context.system.scheduler.scheduleOnce(3 seconds, b, AB)
    }
  }

  class B extends Actor{
    println("new B actor instance created")
    val c = context.actorOf(Props[C], "myc")
    def receive = {
      case Start =>
        c ! BC
      case CB =>
        println("got a CB from C")
      case AB =>
        throw new RuntimeException("foo")
    }
  } 

  class C extends Actor{
    println("new C actor instance created")
    def receive = {
      case BC =>
        Thread.sleep(10000) // simulating long running behavior
        println("done with long processing...")
        sender ! CB
    }
  } 
}
 类似资料:
  • 我对阿克卡很陌生,我有一个(希望)简单的问题。我有一个参与者需要重复执行某个小的子任务——也就是说,每次这个参与者收到消息时,它都必须执行N个子任务。这个子任务是我指定给儿童演员的。我的问题是,我是否应该为每个子任务创建一个新的子角色实例?或者我应该简单地产生一个孩子演员,并发送N条消息?在这种情况下,最好的做法是什么? 为了更好地说明我的问题,这里有两个简化的示例(在Java中-但希望对Scal

  • 我经常发现自己使用一个“主”角色,为子任务创建许多子角色。当子任务完成时,主角也应该停止自己。所以当时,我观察子角色并停止主角色context.children.is。 我经常使用这种模式,但因为我从未读过这方面的文章。我不确定,这是一个好主意还是失败的演员有问题。。。? 我已经读过Akka 2中的关机模式,但是这种方法在Java中似乎比我的解决方案更复杂? 以下是我针对具有两个子任务的主要参与者

  • 让我们假设一个使用Akka Typed实现的应用程序有一个持久执行元。这个持久执行元作为其操作的一部分创建了瞬态(或非持久)子执行元,每个子执行元都有一个唯一的ID,这些ID是持久状态的一部分。持久执行元还需要一些与其子级通信的方式,但我们不希望持久化子级的,因为它们实际上不是状态的一部分。在恢复时,持久参与者应该基于恢复的状态重新创建它的子级。这听起来并不像是一个很不寻常的用例,我正在试图弄清楚

  • 我有几个演员在一个池子里。我希望这些演员中的每一个都能创造出儿童演员。问题是,当我创建子角色并保存引用时,我永远不知道哪个子角色将获得池化角色发送给它的消息。该池被创建为smallstMailBox池。在池演员的构造函数中,我这样做: 这是我的孩子。我做一些花样。有人问,也有人说,但结果不是同一个孩子。首先我做一个: 后来我一遍又一遍地做: (adReceive和adSend是AkkaDocume

  • 我正在学习Akka类型的Actor库,并尝试使用。但是它返回一个类型,而不是我最初创建的子参与者的类型- 我所做的解决方法是在创建时将子对象简单地存储在hashmap中。但这不是一个可伸缩的。 我该如何实现这一点?尤其是在分布式场景下?

  • null 文档明确指出,在重新启动参与者时,当前消息将丢失,必须处理这一问题。然而,它没有明确提到同样的情况是否适用于简历。它是否继续处理这些消息(假设某些外部因素导致了异常,而异常已经不存在了),还是继续处理邮箱中的下一条消息?