Akka 2.6 在非 Actor 类中发现 Actor在 ActorSystem 之外获取 ActorRef

问题描述

我正在与 Akka 合作,目前我有以下协议。

enter image description here

在我的协议中,我有一个服务器,它只负责创建资源(房间和 gabblers)。这些资源被创建,然后被访问。接下来,我想通过一个键来找到相应的 Gabbler ActorRef 来发送消息,但这一次是从一个公开了 API / 方法的类中发送的,而该类不是一个演员。我看过文档,令我难以置信的是,演员系统中没有一种方法可以从其层次结构中返回特定演员以使用它。我已经阅读了接待员部分,虽然我不太清楚,但我看到它再次面向演员。 Akka中没有根据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");
    }
    
}

上图中的协议已经实现,但我无法理解上面的要求。

解决方法

一般来说,为了从演员到演员系统外部(例如 main 方法)获取数据,您需要处理 ask pattern。使用询问模式时,您需要设计您的消息协议来支持它,通常是通过让旨在被询问的消息具有 ActorRef<ReplyMsg> 字段(通常命名为 replyTo)。 akka.actor.typed.javadsl.AskPattern.ask 有效地​​创建了一个短期角色,将那个角色的 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()

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...