Akka 2.6 Actor Discovery In A Non-Actor Class(在 ActorSystem 之外获取 ActorRef)

Akka 2.6 Actor Discovery In A Non-Actor Class (Get ActorRef Outside ActorSystem)

目前我正在使用 Akka,我有以下协议。

在我的协议中,我有一个服务器只负责创建资源(房间和 gabbler)。创建并访问这些资源。接下来,我想通过一个键找到相应的 Gabbler ActorRef 来发送消息,但这次是从 class 公开一个 API / 不是演员的方法。我看过文档,令我难以置信的是,actor 系统中没有一种方法可以 return 其层次结构中的特定 actor 来使用它。我已经阅读了接待员部分,虽然我不是很清楚,但我看到它再次面向演员。 Akka 中没有方法 returns 引用基于 Actor 的路径?

package co.test;

import akka.actor.typed.ActorSystem;
import akka.actor.typed.javadsl.AskPattern;
import akka.actor.typed.receptionist.Receptionist;
import co.test.actors.ChatServer;

public class ChatServerApplication {

    public static void main(String[] args) {
        
        ActorSystem<ChatServer.ServerCommand> system = 
            ActorSystem.create(ChatServer.create(), "chat-server");
        
        system.tell(new ChatServer.NewEventRoom("room1"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user1"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user2"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user3"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user4"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user5"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user6"));
        system.tell(new ChatServer.AttendeeJoin("room1", "user7"));
        
        //ActorRef<Gabbler.Command> gabbler = get specific Gabbler ActorRef
        //gabbler.tell(new Gabbler.SendMessage("test");
    }
    
}

上图中的协议已经实现,但我仍然无法理解上面的问题。

一般来说,要从 actor 获取数据到 actor 系统外部(例如 main 方法),您需要处理 ask pattern。使用询问模式时,您需要设计消息协议以支持它,通常是让要询问的消息具有 ActorRef<ReplyMsg> 字段(通常命名为 replyTo)。 akka.actor.typed.javadsl.AskPattern.ask 有效地创建了一个短暂的 actor,将该 actor 的 ActorRef 注入到消息中,如果它在超时期限内收到一条消息,它会用该消息完成一个 CompletionStage

在此应用程序中,由于您要路由从 mainsystem 参与者的所有内容,因此您可以定义 ChatServer.GetAttendee 消息:

// assuming that there's an interface Command {} already in ChatServer
public class ChatServer extends AbstractBehavior<ChatServer.Command> {
  public static class GetAttendee extends Command {
    public final String room;
    public final String user;
    public final ActorRef<ChatServer.AttendeeIs> replyTo;

    public GetAttendee(String room, String user, ActorRef<ChatServer.AttendeeIs> replyTo) {
      this.room = room;
      this.user = user;
      this.replyTo = replyTo;
    }
  }

  public static class AttendeeIs {
    public final ActorRef<Gabbler.Command> ref

    public AttendeeIs(ActorRef<Gabbler.Command> ref) {
      this.ref = ref;
    }
  }
}

ChatServer 可能会在相应的 ChatRoom 上传递消息)

在您的 main 中,您可以发送类似

的询问
String desiredRoom = "whatever";
String desiredUser = "whoever";

CompletionStage<ChatServer.AttendeeIs> getGabbler =
  AskPattern.ask(
    system,
    replyTo -> new ChatServer.GetAttendee(desiredRoom, desiredUser, replyTo),
    Duration.ofSeconds(15),
    system.scheduler()
  )

 CompletionStage<ActorRef<Gabbler.Command>> gabblerFuture =
   getGabbler.thenCompose(
     (ChatServer.AttendeeIs response) ->
       return CompletableFuture.completedFuture(response.ref)
   )

 ActorRef<Gabbler.Command> gabbler = gabblerFuture.toCompletableFuture().get()