如何解决寻找允许类产生actor的抽象
我有一个类向其客户提供不同类型的 Source
。当 Source
运行时,应该产生一个演员,将新条目提供给相应的流。所以我的班级需要能够产生演员。我知道有两种方法可以做到这一点:使用另一个演员的 ActorContext
或使用 ActorSystem
。是否有生成新actor 的通用抽象,以便我可以在我的类中注入一个帮助程序,它只允许它在需要时生成actor,而不管它是如何完成的?
我为此创建了一个 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 - 不支持从外部访问 ActorContext 演员 [akka://...]。 Actor 当前没有处理任何消息,但是 ActorContext 是从 Thread[...]
调用的在升级之前这似乎不是问题,但现在我想知道我所做的是否是可取的,或者这是否是一种反模式。
解决方法
我知道有两种方法可以做到这一点:使用另一个演员的 ActorContext 或使用 ActorSystem
我认为这适用于 Classic(即无类型)Actor API,并且通用抽象是 akka.actor.ActorRefFactory
,akka.actor.ActorSystem
和 akka.actor.ActorContext
都对其进行了扩展。这就是 def actorOf(props: Props): ActorRef
用于创建新演员的地方。
在新类型的 Actor API 中,情况不再如此。您不能从 akka.actor.typed.ActorSystem
创建演员,您只能从 akka.actor.typed.scaladsl/javadsl.ActorContext
使用 spawn*
系列方法创建它,给定演员系统的监护人/根演员除外,您可以可以由 ActorSystem(guardianBehavior: Behavior[T],name: String)
和朋友在 Scala 中创建或在 Java 中使用 ActorSystem.create(...)
等价物创建。
ActorContext
只能从拥有它的参与者的消息处理线程或从 setup
方法访问,并且生成错误日志的运行时检查自 2.6.6
.您可能从其他地方调用该对象。也许这篇文章将有助于跟踪确切位置:https://discuss.lightbend.com/t/akka-2-6-6-context-log-error-string-failed/6708/2
在 Typed 中,除了守护 actor(在创建 ActorSystem
时创建的那个),actor 只能由其他 actor 生成。
在很多情况下,在 actor 之外执行的代码想要生成一个 actor。为此,您可以向演员发送消息,并让该演员生成具有所需行为的演员。
如果您的 actor 的唯一目的是产生其他 actor,则 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,_))
}
}
如果您的监护人 actor 碰巧仅按需生成其他 actor,它可以实现 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,_))
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。