简体   繁体   English

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

[英]How can i check if an Akka actor exists (akka 2.2)?

I have a java object which is not an actor which selects actors from an actor system with actorSelection(Path)). 我有一个java对象,它不是一个使用actorSelection(Path)从actor系统中选择actor的actor。 It is possible, that the selected actor does not exist in the system. 系统中可能存在所选的actor。

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(),因此我无法向actor选择发送和识别消息并使用响应的发送者。

I tried to solve the problem by sending the message to the actor anyway via the actor selection and then reacting to the deadletter. 我试图通过演员选择向演员发送消息然后对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);

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). 我正在研究的一个问题是,定义它的方法可能同时被调用(来自其他actor)。 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. 因此,如果由于仍在创建actor而使resolveOne调用失败,则可能会遇到竞争条件,其中您尝试创建两次actor。 This might or might not be an issue for your use case 这可能是也可能不是您的用例的问题

It looks like Akka left off support for ActorSelection on the java api for ask . 它看起来像阿卡不放过支持ActorSelection的Java API来ask I played with the code a little and I found something that works though. 我玩了一些代码,但我发现了一些有用的东西。 See if this code works for you: 看看这段代码是否适合你:

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. 我只是看看scala如何通过java来支持支持工作并将其挂钩。 This worked for me; 这对我有用; I'm hoping it works for you. 我希望它适合你。

Akka provides a functionality to get an ActorRef from an ActorSelection using a special message Identify . Akka提供了使用特殊消息IdentifyActorSelection获取ActorRef的功能。 You don't have to use ask() for this message. 您不必对此消息使用ask() Simply pass an Identify-message to the ActorSelection and listen for an ActorIdentity message that will be passed back to you. 只需将Identify-message传递给ActorSelection,然后侦听将传递给您的ActorIdentity消息。 There is an example for exactly this in the Akka docs: Identifying Actors via Actor Selection (Java) 在Akka文档中有一个这样的例子: 通过Actor选择识别Actor(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 graphic that shows the relations between ActorPath, ActorSelection and the Actor Lifecycle in the docs. 还有一个非常漂亮的图形 ,显示了Actor中的ActorPath,ActorSelection和Actor Lifecycle之间的关系。

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). 这意味着如果该actor忙,它将不会回复,并且失败(超时)。

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. 在一个更混合的普通Java / Akka设置中,它很容易被咆哮。 In particular, code within an actor's thread cannot find a reference to that actor. 特别是,actor的线程中的代码找不到对该actor的引用。

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)
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM