Как я могу проверить, существует ли актер Akka (akka 2.2)?
У меня есть объект java, который не является актором, который выбирает актеров из системы актеров с actorSelection (Path)). Вполне возможно, что выбранный актер не существует в системе.
в Java Api ask () не существует для ActorSelection, поэтому я не могу отправить и идентифицировать сообщение для выбора актера и использовать отправителя ответа.
Я попытался решить проблему, отправив сообщение актеру в любом случае через выбор актера, а затем реагируя в недоставленных. Но я не получаю никаких deadletters.
Как я могу проверить с помощью 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);
5 ответов
похоже, что Akka прекратила поддержку ActorSelection
на Java API для 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);
}
}
Я просто посмотрел, как работает поддержка Scala ask и подключается к ней через 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
}
одна проблема, которую я все еще исследую, заключается в том, что метод, где это определено, может быть вызван одновременно (от других субъектов). Поэтому можно получить условие гонки, когда вы пытаетесь создать актера дважды, если вызов resolveOne терпит неудачу, потому что актер все еще создается. Это может быть или не быть проблемой для вашего варианта использования
Akka предоставляет функциональность, чтобы получить ActorRef
С ActorSelection
используя специальное сообщение Identify
. Вы не должны использовать ask()
для этого сообщения. Просто передайте Identify-message в ActorSelection и слушайте ActorIdentity
сообщение, которое будет передано обратно к вам. Для этого есть пример в документах Akka:идентификация актеров с помощью выбора актера (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
}
}
}
}
там также очень приятно графика это показывает отношения между ActorPath, ActorSelection и жизненным циклом актора в документах.
Как отмечают другие ответы,ActorSelection.resolveOne()
обрабатывает это.
одно предупреждение: под капотом это работает, отправляя сообщение соответствующему актеру. Это означает, что если этот актер занят, он не ответит, и это не удастся (с таймаутом).
в pure-best-practice-Akka это, вероятно, угловой случай. В более смешанной настройке normal-Java / Akka легко запутаться. В частности, код в потоке субъекта не может найти ссылку на этого субъекта.
при использовании версии 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)
}