【问题标题】:Akka-Java Routing IssueAkka-Java 路由问题
【发布时间】:2017-09-22 01:03:01
【问题描述】:

我在 Akka-Java 中有以下问题。

我有一个父 Actor MainActor.class,这个父有 5 个子路由。以下是层次结构:

My App => Main Actor => [Child Route-1,Child-Route-2,..]

简单用例是将字符串输入解析为整数作为输出:

MyApp ===ask[string input]===> Main Actor ==route==> Child(parses to Integer) === integer result===> Main Actor ===result==> MyApp

这里是主角sn-p:

class MainActor extends UntypedActor {
 Router router; {
  // ...routes are configured here
 }

 public void onReceive(Object message) {
  if (message instanceof String) {
   router.route(message, self()); // route it to child
  } else if (message instanceof Integer) {
   // received from child, 'tell' this result to actual sender/parent i.e, MyApp
   sender().tell(message, self());
  } else unhandled(message);
 }
}

Child Actor 除了将 String 解析为 Integer 并获取结果并通过 sender().tell(result,getContext().parent()) 将其发送回其发送者之外,什么都不做

问题

MainActor 正在将 child 发送的 Parsed 整数结果发送回 child 本身,而不是 MyApp。我还尝试将MainActor 中的sender() 替换为getContext().parent(),但仍然无效。

【问题讨论】:

    标签: java akka


    【解决方案1】:

    由于您从 MainActor 的子 Actor 接收整数,因此发送者指向子 Actor。 当您在 sender 上调用 tell 时,它会将消息返回给子 Actor。

    这应该有效: getContext().parent().tell(message, self())

    【讨论】:

    • 我尝试将sender() 替换为getContext().parent(),正如我在帖子中提到的那样,没有运气。
    【解决方案2】:

    你有两个选择:

    您可以通过转发消息(参见 self() -> sender() 更改)直接从您的孩子转到您的应用(在返回的路上绕过根 actor):

    if (message instanceof String) {
      router.route(message, sender());
    }
    

    所以当孩子响应时,他的发件人现在是应用程序而不是根。

    或者,您可以使用期货,特别是the ask/pipe patten

    【讨论】:

      【解决方案3】:

      你真的应该选择Diego Martinola 's answer

      您的代码不起作用的原因如下:

      • 当你使用sender().tell(message, self)时,sender()不是MainApp,因为sender()给你当前正在处理的消息的发送者。由于您正在处理来自子 Actor 的 Integer 消息,因此您将消息发送回给它。
      • 您尝试的修改,即getContext().parent().tell(message, self) 也不好。在这种情况下,您将发送到 MainActor 的父级,而不是 MainApp。其实我怀疑 MainApp 甚至不是演员,对吧?您只能向演员发送消息。如果您的意图是将初始消息发送回给 MainActor 的 actor,请记住这不是 MainApp,它是 Patterns.ask 使用的临时 actor。无论如何,要点是,在 Integer 消息的处理程序中,您无法获取该临时演员的 ActorRef,因为如前所述,sender() 给出了当前消息的发送者。一种解决方法可能是在字符串消息的处理程序中获取发送者并将其存储在变量中以供以后使用,如下所示:

        class MainActor extends UntypedActor {
         ActorRef lastRequester;
         Router router; {
          // ...routes are configured here
         }
        
         public void onReceive(Object message) {
          if (message instanceof String) {
           lastRequester = sender();
           router.route(message, self()); // route it to child
          } else if (message instanceof Integer) {
           lastRequester.tell(message, self());
          } else unhandled(message);
         }
        }
        

      但这很危险,因为您将依赖所有在下一条 String 消息之前到达的 Integer 消息;如果第一个 String 消息的 Integer 消息在第二个 String 消息之后到达,它将被发送给发送第二个 String 的 actor。等待所有孩子回答并不是一个真正的选择,因为 Akka 为您提供最多一次交付语义。您必须创建一种机制来识别某个 Integer 消息关联到的 String 消息,并保留 ActorRef 列表而不是单个列表。

      虽然后者实施起来并不十分复杂,但对于您的用例来说并不值得,而且我想说在大多数路由场景中,Diego Martinola 's answer 是要走的路。

      【讨论】:

        猜你喜欢
        • 2014-02-28
        • 1970-01-01
        • 1970-01-01
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-30
        • 2016-10-04
        相关资源
        最近更新 更多