0

我正在将现有应用程序从 Akka Classic 移植到 Akka Typed。最初,您可以使用以下方式获得对演员的引用context.actorSelection().resolveOne()

我知道在 Akka Typed 中不再支持这一点,我们应该使用它Receptionist来注册演员以通过ServiceKey.

但是,我只想将消息发送到本地参与者,即集群中每个节点上都存在的本地单例。我有它的本地路径,但没有直接引用它。这是因为它是由 Akka 管理系统创建的健康检查参与者。

从文档中可以看出,Receptionist使用 ServiceKey 注册参与者可以使其对集群的所有成员可用。因此,如果我查询,我将收到对所有节点上的单例参与者的引用ServiceKey

似乎没有办法在Receptionist唯一的本地注册,并且在集群中发布这些内部引用似乎不必要地泄漏并违反封装。ListingReceptionist. _ 我想ServiceKey用于注册的可能是系统特定的?

我在这里错过了一个明显的解决方案吗?

4

1 回答 1

1

在 Akka Management Actor 的特殊情况下,因为该项目不依赖于 Akka Typed(因此涉及的 Actor 是 Classic Actor),您可以将您的 TypedActorContext视为 ClassicActorContext并使用ActorSelection.

根据您的问题,我猜测 Java (在 Scala 中,隐式使这变得不那么冗长,也许可以澄清意图):

akka.actor.typed.javadsl.Adapter.toClassic(context).actorSelection(path).resolveOne(timeout)

对于只想解析 Typed 本地参与者的情况,我发现最有效的策略是将解析功能合并到创建ActorSystem. 想要找到的演员将在 中注册,ActorSystem其他演员可以ActorSystem要求ActorRef

这里的一个微妙之处是它context.getSystem()给了你一个ActorSystem<Void>which extends ActorRef<Void>。你可以通过调用来解决这个unsafeUpcast问题ActorSystem,例如

// Might not actually be syntactically valid Java, but hopefully the fix to make it
// legal is obvious...
ActorRef<MyActorSystemCommand> systemRef = context.getSystem().unsafeUpcast<MyActorSystemCommand>()

请注意,获取ActorSystem正确的消息类型非常重要:如果ActorSystem' 的行为不接受该类型的消息,则 Actor 系统将崩溃(据我所知,没有办法阻止 Actor 系统关闭)当您发送消息时。

这种方法的一个演变是定义一个在ActorSystem启动时产生的仅限本地的接待员演员:希望与该接待员交互的演员ActorRef通过上述方法获得它,然后该演员处理解决方案。

当然请注意,在这两种方法中(与 cluster-aware 一样Receptionist),只有明确选择像这样被解析的参与者才是可解析的。这与 Akka Typed 的一个基本主题是一致的:让演员更多地负责它向外界暴露的程度。

于 2021-08-27T19:59:29.077 回答