akka 寻找允许类产生参与者的抽象

mklgxw1f  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(194)

我有一个类,它为客户端提供不同类型的Source。当Source运行时,应该产生一个actor,它将新的条目馈送到相应的流中。所以我的类需要能够产生actor。我知道两种方法来做到这一点:使用另一个演员的ActorContext或使用ActorSystem。是否有一个通用的抽象来生成新演员,以便我可以在我的类中注入一个助手,在需要时允许它生成演员,而不管它是如何完成的?
为此,我创建了一个ActorSpawner接口,到目前为止,它运行得非常好:

trait ActorSpawner {

  def spawn[T](behavior: Behavior[T]): ActorRef[T]

  def spawn[T](behavior: Behavior[T], name: String): ActorRef[T]

}

但是,自从我升级到Akka 2.6后,我经常收到以下错误消息:

  • 错误akka.actor.SupervisorStrategy -不支持从参与者[akka://...]外部访问ActorContext。参与者当前未处理任何消息,但从线程[...]调用了ActorContext *

在升级之前,这似乎不是一个问题,但现在我想知道我所做的是否是可取的,或者这是一种反模式。

nuypyhwy

nuypyhwy1#

在Typed中,除了监护执行元(创建ActorSystem时创建的执行元)之外,执行元只能由其他执行元派生。
仍然有很多情况下,在执行元外部执行的代码希望派生一个执行元。为此,您可以向执行元发送一条消息,并让该执行元派生具有所需行为的执行元。
如果您有一个唯一目的是产生其他参与者的参与者,Akka会包含SpawnProtocol,它与ask模式兼容:

trait ActorSpawner {
  def spawn[T](behavior: Behavior[T], name: String): Future[ActorRef[T]]

  def spawn[T](behavior: Behavior[T]): Future[ActorRef[T]] = spawn(behavior, "")
}

def spawnerFor(spawningActor: ActorRef[SpawnProtocol.Spawn])(implicit system: ActorSystem[Nothing]): ActorSpawner = {
  import system.executionContext
  import akka.actor.typed.scaladsl.AskPattern._

  implicit val timeout = Timeout(10.seconds)  // or whatever, can also make this an arg

  new ActorSpawner {
    def spawn[T](behavior: Behavior[T], name: String): Future[ActorRef[T]] =
      spawningActor.ask(SpawnProtocol.Spawn(behavior, name, Props.empty, _))
  }
}

如果守护角色碰巧只在需要时产生其他角色,它可以实现SpawnProtocol,在这种情况下,ActorSystem本身就是ActorRef[SpawnProtocol.Spawn],因此可以进一步简化为

def spawnerFor(system: ActorSystem[SpawnProtocol.Spawn]): ActorSpawner = {
  import system.executionContext
  import akka.actor.typed.scaladsl.AskPattern._

  implicit val timeout = Timeout(10.seconds)
  implicit val scheduler = system.scheduler

  new ActorSpawner {
    def spawn[T](behavior: Behavior[T], name: String): Future[ActorRef[T]] =
      system.ask(SpawnProtocol.Spawn(behavior, name, Props.empty, _))
  }
}
wz8daaqr

wz8daaqr2#

我知道有两种方法:使用另一个执行元的ActorContext或使用ActorSystem
我认为这对于Classic(即非类型化)Actor API是正确的,常见的抽象是akka.actor.ActorRefFactoryakka.actor.ActorSystemakka.actor.ActorContext都对其进行了扩展。
在新的类型化Actor API中,情况不再是这样了。你不能从akka.actor.typed.ActorSystem创建一个Actor,你只能从akka.actor.typed.scaladsl/javadsl.ActorContext使用spawn*家族的方法创建它,除了给定Actor系统的监护人/根Actor,你可以在Scala中通过ActorSystem(guardianBehavior: Behavior[T], name: String)和朋友创建,或者在Java中使用ActorSystem.create(...)等价物创建。
ActorContext只能从拥有它的参与者的消息处理线程或从setup方法访问,并且生成错误日志的运行时检查自2.6.6起就已到位。您可能从其他地方调用该对象。也许这篇文章在跟踪确切位置时会很有用:https://discuss.lightbend.com/t/akka-2-6-6-context-log-error-string-failed/6708/2

相关问题