Java 如何检查 Akka 演员是否存在(akka 2.2)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18012945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i check if an Akka actor exists (akka 2.2)?
提问by schrums
I have a java object which is not an actor which selects actors from an actor system with actorSelection(Path)). It is possible, that the selected actor does not exist in the system.
我有一个 java 对象,它不是一个演员,它从演员系统中使用 actorSelection(Path) 选择演员。系统中可能不存在所选参与者。
In the Java Api ask() does not exist for ActorSelection, so I can not send and Identify message to the actor selection and use the sender of the response.
在 Java Api 中,ActorSelection 不存在 ask(),因此我无法向演员选择发送和识别消息并使用响应的发送者。
I tried to solve the problem by sending the message to the actor anyway via the actor selection and then reacting to the deadletter. But I don't get any deadletters.
我试图通过演员选择向演员发送消息,然后对死信做出反应来解决这个问题。但我没有收到任何死信。
How can I check with the ActorSelection if the actor is alive or does not exist?
如果演员还活着或不存在,我如何检查 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);
采纳答案by cmbaxter
It looks like Akka left off support for ActorSelection
on the java api for ask
. I played with the code a little and I found something that works though. See if this code works for you:
看起来 Akka 停止了ActorSelection
对 java api for 的支持ask
。我稍微玩了一下代码,但我发现了一些可行的东西。看看这个代码是否适合你:
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<Object> fut = asker.ask(new Identify(1), t);
ActorIdentity ident = (ActorIdentity)Await.result(fut, t.duration());
ActorRef ref = ident.getRef();
System.out.println(ref == null);
}
}
I just looked at how the scala ask support worked and hooked into it via java. This worked for me; I'm hoping it works for you.
我只是看看 scala ask 支持是如何工作的,并通过 java 连接到它。这对我有用;我希望它对你有用。
回答by Bj?rn Jacobs
Akka provides a functionality to get an ActorRef
from an ActorSelection
using a special message Identify
. You don't have to use ask()
for this message. Simply pass an Identify-message to the ActorSelection and listen for an ActorIdentity
message that will be passed back to you. There is an example for exactly this in the Akka docs: Identifying Actors via Actor Selection (Java)
Akka 提供了ActorRef
一种ActorSelection
使用特殊消息从 an获取的功能Identify
。您不必使用ask()
此消息。只需将识别消息传递给 ActorSelection 并侦听ActorIdentity
将传回给您的消息。Akka 文档中有一个关于此的示例:Identing Actors via Actor Selection (Java)
This code is taken from the example and modified:
此代码取自示例并进行了修改:
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
}
}
}
}
There is also a very nice graphicthat shows the relations between ActorPath, ActorSelection and the Actor Lifecycle in the docs.
还有一个非常漂亮的图形显示了文档中的 ActorPath、ActorSelection 和 Actor Lifecycle 之间的关系。
回答by Mario Camou
I recently found the ActorSelection.resolveOne method:
我最近发现了 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
}
One problem I'm still investigating is, the method where this is defined might be called concurrently (from other actors). Therefore it's possible to get a race condition where you try to create the actor twice if the resolveOne call fails because the actor is still being created. This might or might not be an issue for your use case
我仍在研究的一个问题是,定义 this 的方法可能会被并发调用(从其他参与者)。因此,如果 resolveOne 调用失败,则可能会出现竞争条件,您尝试创建该角色两次,因为该角色仍在创建中。这可能是也可能不是您的用例的问题
回答by Daniel Winterstein
As other answers note, ActorSelection.resolveOne()
handles this.
正如其他答案所指出的,ActorSelection.resolveOne()
处理这个。
One warning: Under the hood, this works by sending a message to the actor in question. Which means if that actor is busy, it won't reply, and this fails (with a timeout).
一个警告:在幕后,这是通过向相关演员发送消息来实现的。这意味着如果那个演员很忙,它不会回复,这会失败(超时)。
In pure-best-practice-Akka, this is probably a corner-case. In a more mixed normal-Java / Akka setup, it's easy to get snarled up though. In particular, code within an actor's thread cannot find a reference to that actor.
在纯最佳实践 Akka 中,这可能是一个极端情况。不过,在更混合的普通 Java / Akka 设置中,很容易被激怒。特别是,actor 线程中的代码无法找到对该actor 的引用。
回答by Ivan Gonzalez
Using version 2.3.4
使用版本 2.3.4
Some Scala example, maybe can help
一些 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)
}