我怎样才能检查Akka演员是否存在(akka 2.2)?

我有一个java对象,它不是一个使用actorSelection(Path)从actor系统中选择actor的actor。 系统中可能存在所选的actor。

在Java Api中,ActorSelection不存在ask(),因此我无法向actor选择发送和Identify消息并使用响应的发送者。

我试图通过演员选择向演员发送消息然后对deadletter做出反应来解决问题。 但我没有任何动静。

如果演员活着还是不存在,我如何检查ActorSelection?

ActorSystem system = ActorSystem.create("test"); //create test actor system.actorOf(Props.create(TestActor.class), "testActor"); //add dead letter listener to the system ActorRef eventBusActor = asys.actorOf(Props.create(EventBusActor.class), "eventbusactor"); system.eventStream().subscribe(eventBusActor, DeadLetter.class); //This works. The test actor receives the message ActorSelection a1 = asys.actorSelection("/user/testActor"); a1.tell("hello", ActorRef.noSender()); //This does not work and does not send dead letters ActorSelection a2 = asys.actorSelection("/user/doesnotexist"); a2.tell("hello", ActorRef.noSender()); //Does not compile, because ask needs an ActorRef as first argument ActorSelection a3 = asys.actorSelection("/user/test"); Future f = Patterns.ask(a3, new Identify(), 1000); 

看起来Akka在java api上停止了对ActorSelection支持。 我玩了一点代码,然后我发现了一些有用的东西。 看看这段代码是否适合你:

 import java.util.concurrent.TimeUnit; import scala.concurrent.Await; import scala.concurrent.Future; import akka.actor.ActorIdentity; import akka.actor.ActorRef; import akka.actor.ActorSelection; import akka.actor.ActorSystem; import akka.actor.Identify; import akka.actor.Props; import akka.pattern.AskableActorSelection; import akka.util.Timeout; public class AskTest { public static void main(String[] args) throws Exception{ ActorSystem sys = ActorSystem.apply("test"); sys.actorOf(Props.create(TestActor.class), "mytest"); ActorSelection sel = sys.actorSelection("/user/mytest"); Timeout t = new Timeout(5, TimeUnit.SECONDS); AskableActorSelection asker = new AskableActorSelection(sel); Future fut = asker.ask(new Identify(1), t); ActorIdentity ident = (ActorIdentity)Await.result(fut, t.duration()); ActorRef ref = ident.getRef(); System.out.println(ref == null); } } 

我只是看看scala如何通过java来支持支持工作并将其连接到它。 这对我有用; 我希望它适合你。

我最近发现了ActorSelection.resolveOne方法:

 val name = "myActor" implicit val timeout = 5000 // Timeout for the resolveOne call system.actorSelection(name).resolveOne().onComplete { case Success(actor) => actor ! message case Failure(ex) => val actor = system.actorOf(Props(classOf[ActorClass]), name) actor ! message } 

我正在研究的一个问题是,定义它的方法可能同时被调用(来自其他actor)。 因此,如果由于仍在创建actor之前resolveOne调用失败,则可能会遇到竞争条件,其中您尝试创建actor两次。 这可能是也可能不是您的用例的问题

Akka提供了使用特殊消息IdentifyActorSelection获取ActorRef的function。 您不必对此消息使用ask() 。 只需将Identify-message传递给ActorSelection,然后侦听将传递给您的ActorIdentity消息。 在Akka文档中有一个这样的例子: 通过Actor选择识别Actor(Java)

此代码取自示例并已修改:

 final String identifyId = "1"; @Override public void onReceive(Object message) { if (message instanceof ActorIdentity) { ActorIdentity identity = (ActorIdentity) message; if (identity.correlationId().equals(identifyId)) { ActorRef ref = identity.getRef(); if (ref == null) // Actor does not exist else { // Actor does exist } } } } 

还有一个非常漂亮的图形 ,显示了Actor中的ActorPath,ActorSelection和Actor Lifecycle之间的关系。

正如其他答案所述, ActorSelection.resolveOne()处理此问题。

一个警告:在引擎盖下,这是通过向相关演员发送消息来实现的。 这意味着如果该actor忙,它将不会回复,并且这会失败(超时)。

在纯粹的最佳实践 – 阿卡,这可能是一个角落案例。 在一个更混合的普通Java / Akka设置中,它很容易被咆哮。 特别是,actor的线程中的代码无法找到对该actor的引用。

使用版本2.3.4

一些Scala的例子,也许可以提供帮助

  val zed2 = Akka.system().actorSelection("path") val fs:FiniteDuration = (100).millis val x = zed2.resolveOne(fs).value if (x.isDefined){ println(x.get.isFailure) }