【问题标题】:Akka Actor Path for that instance该实例的 Akka Actor Path
【发布时间】:2016-07-18 16:49:15
【问题描述】:

我正在使用 Java Play 框架。 我正在使用 Web 套接字进行客户端服务器交互。 在服务器端,我们有响应客户端请求的又名演员。 我面临的问题: 我希望,当客户端打开与服务器上的 Hakka 演员的 Web 套接字连接时,它实际上为该演员打开了一个池,然后我需要跟踪该实例的演员客户端路径,以便每当采取其他行动时放置在某个其他类中,该类通知该参与者(使用跟踪的实例路径)该操作已发生,然后该参与者通知用户(客户端)该操作已发生。 我实际上正在使用

String ClientPushActorPath = akka.serialization.Serialization.serializedActorPath(self());

以上内容继续获取该客户端用户实例的路径。 但是下次当我尝试使用这条路径击中这个演员时,我找不到这个演员。 我试图从另一个演员那里打演员的方式是:

PushCacheManager cache = PushCacheManager.getInstance();
cache.load(qiid);
String ActorPath = cache.get("ClientPushActorPath");
ActorSelection ClientPushActor = system.actorSelection(ActorPath);
ClientPushActor.tell(m4, getSelf());

所以上面的代码简单地说,首先我去从缓存中获取 scots 路径(它被缓存在内存中以备将来使用),然后我尝试将该路径传递给演员选择。一旦我得到演员的对象选择我用它来告诉其他演员我需要传递的消息是 m4。 请纠正我哪里出错了。 我无法看到使用此路径的演员。 我觉得,我跟踪路径的方式是错误的。 请纠正我。 比

【问题讨论】:

  • 你为什么要打扰ActorPath?是什么阻止您将ActorRef 存储在某处并使用它来发送回复?使用ActorRef 是在 Akka 中的惯用方式
  • 是否可以存储特定客户端用户实例的参与者引用?对不起,我是 akka 的新手。
  • 我的意思是,如果您有 100 个用户同时登录,那么所有这 100 个用户都应该有一个唯一的参与者参考,以后可以使用它来通知这些用户。
  • 为每个 websocket 客户端/用户创建一个服务器端参与者。只要你有正确的命名或依赖 Akka 的内部命名(第一种方法是推荐的),应该没有任何问题。而且您所有的ActorRefs 都将是唯一且可序列化的。
  • 能否提供参考链接(如果有)

标签: java playframework playframework-2.0 akka


【解决方案1】:

请耐心等待,这将需要一些时间来完成,但它应该让您知道该怎么做。注意:我假设您仍在使用 Play 2.4.x 并且尚未更新到 Play 2.5.x。还有你使用 Java(虽然如果你能够切换,我会推荐 Akka Scala API)。


第 1 步:定义处理 WebSocket 连接的参与者

在你的控制器中你可以这样写:

public static WebSocket<String> socket() {
    return WebSocket.withActor(MyWebSocketActor::props);
}

这意味着每个 WebSocket 连接都将由 MyWebSocketActor 类型的参与者实例处理。然后,您必须像这样实现演员:

import akka.actor.*;

public class MyWebSocketActor extends UntypedActor {

    public static Props props(ActorRef out) {
        return Props.create(MyWebSocketActor.class, out);
    }

    private final ActorRef out;

    public MyWebSocketActor(ActorRef out) {
        this.out = out;
    }

    public void onReceive(Object message) throws Exception {
        if (message instanceof String) {
            out.tell("I received your message: " + message, self());
        }
    }
}

您看到的ActorRef out 参数实际上是底层actor(从Play 生成)。你不需要对它做任何事情,只要记住,一旦你向这个out演员发送了一些东西,他就会将它处理给客户端。

您还必须在 routes 文件中定义正确的路由:

GET /ws controllers.Application.socket()

第 2 步:定义如何管理所有 WebSocket 参与者

一般来说,您有两种选择 - 要么“查找”上面创建的参与者,要么提供某种机制来管理它们(某种注册表)

  • 第 2.1 步:查找 WebSocket 演员

    这里的优点是您不需要额外的注册表/管理器或类似的东西。缺点是很难知道哪个actor服务于哪个WebSocket连接。

    您可以为此使用actorSelection:

    system.actorSelection("system/websockets/*/handler");

    这是可行的,因为正如我之前提到的,Play 生成了连接处理程序参与者 - 所以它们的地址是这样的:akka://application/system/websockets/42/handler。同样,这样您可以获得所有演员,但不能获得单个演员(因为您不知道他们的处理程序编号)。

  • 步骤 2b:管理 WebSocket 参与者 这里的优点是您可以完全管理演员并为他们分配各种信息。缺点是你要多照顾一个演员(虽然这不是问题,Akka 很擅长)

你会创建一个新的actor,比如:

 public class ManagerActor extends UntypedActor {

    List<ActorRef> slaves;

    public MyWebSocketActor() {
        this.slaves = new ArrayList<>();
    }

    public void onReceive(Object message) throws Exception {
        if (message instanceof RegisterMe) {
            // a new WebSocket was created so we can register him
            slaves.add(sender());

            // also register a DeathWatch so that we know when the WebSocket actor dies 
            context.watch(sender());
        } else if (message instanceof Terminated) {
            // remove from the list
            ...
        }
    }
 }

第 3 步:整合

现在,还记得我们上面的 WebSocket 演员吗?他应该以某种方式向经理注册。同样,您可以通过两种方式执行此操作:您可以使用context.system.actorSelection("user/manager")“查找”管理器,或者如果您已经有对管理器的引用(ActorRef),则可以在创建时将其作为构造函数参数提供WebSocket 演员

您可以使用每个演员都可以使用的preStart 方法并进行注册:

public class MyWebSocketActor extends UntypedActor {

   ....

   @Override
   public void preStart() throws Exception {
       context().system().actorSelection("user/manager").tell(RegisterMe, self());
       super.preStart();
   }
}

现在您已经拥有了由 ... Manager 管理的所有 WebSocket Actor,您可以定义他可以处理的新消息并告诉他必须将 m4 转发给客户端。请注意,您可以在 Manager 中使用 Map 之类的东西 - 其中 ActorRef 是键,值是某些用户特定的属性或任何您想要的。

【讨论】:

    猜你喜欢
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2017-12-18
    • 2013-02-02
    • 1970-01-01
    相关资源
    最近更新 更多