2017-04-25 63 views
0

在Akka-Java中有以下问题。Akka-Java路由问题

我有一个父代演员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

以下是主要演员片段:

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派遣由孩子送到解析的整数结果返回给孩子本身,而不是MyApp。我也尝试将替换为MainActor中的getContext().parent(),但仍然无效。

回答

0

由于您从MainActor的子actor中接收到Integers,因此发件人会指向子actor。 当您在发件人上调用tell时,它会将消息返回给子actor。

这应该工作: getContext().parent().tell(message, self())

+0

我尝试将'sender()'替换为'getContext()。parent()',正如我在帖子中提到的那样,没有运气。 –

1

你有2种选择:

您可以直接从你的孩子去你的应用程序(绕过根演员回来的路上),通过转发消息(看到自() - >发送方()的变化):

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

所以,当孩子回答,他的发送者现在是应用,而不是根源。

或者,也可以在特定的

0

利用期货,the ask/pipe patten你真的应该用Diego Martinola 's answer去。

为什么你的代码是不工作的原因如下:

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

    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消息之前;如果第一个String消息的Integer消息在第二个String消息后到达,它将被发送给发送第二个String的actor。等待所有孩子回答并不是一个真正的选择,因为Akka给你最多一次交付语义。您将不得不创建一种机制来识别某个Integer消息所关联的String消息,并保留一个ActorRef而不是一个单独消息。

虽然后者的实现起来并不复杂,但对于您的使用情况来说并不值得,而且在大多数路由场景中,Diego Martinola 's answer就是要走的路。