2017-04-25 73 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就是要走的路。