2014-05-09 26 views
4

假設我有一個能夠通過TCP發送和接收消息的IO Actor connection。在我的演員,我問一個響應連接的另一面:詢問模式是否與Akka IO參與者一起工作?

connection.ask(ByteString("stuff")).collect { 
    case Received(response) => log.debug(response.utf8String) 
} 

看來,這段代碼的問未來時間參數,而是含有演員接受詢問模式之外的原始消息。

你可以使用Akka IO actors的ask模式嗎?如果不是,爲什麼不呢?

回答

2

我不知道具體的架構,但在這裏我將如何解釋給自己:

與阿卡IO接口演員這裏的問題是,他們沒有在一個請求 - 響應的方式工作。如果你仔細想想 - 這很有道理,因爲TCP不是一個請求響應協議。 TCP甚至沒有消息的概念。從程序員的角度來看,TCP連接只是一對連續的字節流 - 每個方向一個。而已。

Akka IO是網絡協議之上的一個最小的actor層,所以模仿這種行爲並不奇怪。當TCP參與者從網絡接收到一些數據時,它只知道一件事 - 它應該向最初發送消息Connect的參與者發送Received消息。就這樣。它不知道它從網絡收到的數據與你之前發送的數據有某種關係。

添加到所有這一切,ask模式只有在假設當你發送消息A一些演員,將與消息B正好寄往該消息A發送應對工作。正如我們已經知道的那樣,TCP參與者不會這麼做 - 它只是將所有內容都發送給原始的Connect消息的發件人。

之所以需要這個假設是ask模式實際上產生某種被設置爲發件人使用ask發送的消息一個「幽靈」的演員。然後,這位「幻影」演員將收到回覆並調用在Future上註冊的所有回叫。作爲附註 - 請注意,這些回調函數完全獨立於發送者而被調用,即它們可以同時運行!

所以,我終於得出結論,像這樣使用會與阿卡IO的工作,因爲它只是等級太低了這樣一個抽象的ask模式。如果你仍然需要它,你需要在Akka IO之上爲自己創建一個抽象層,例如一些簡單的中間參與者,覆蓋TCP連接器參與者並實現請求 - 響應行爲。

0

作爲@ ghik答案的附加參考,這裏粗略地說明了我如何創建一箇中間actor來爲其餘演員啓用IO模式。

class IOAskHandlerActor(address: InetSocketAddress) extends Actor { 
    override def receive = { 
     // Connection setup code omitted  
     case Connected(remote, local) => 
     // other code omitted 
     context become latch(sender()) 
    } 

    def latch(connection: ActorRef): Receive = { 
     case outgoing => 
     context become receiving(connection, sender()) 
     connection ! MySerializer.write(outgoing) 
    } 

    def receiving(connection: ActorRef, asker: ActorRef): Receive = { 
     case Received(incoming) => 
     context become latch(connection) 
     asker ! MySerializer.read(incoming) 
    } 
} 

此類的實例可以是ask ed用於響應。請注意,我只用一個同步提問者(這是我的用例)進行了測試,這可能不適用於多個提問者。

相關問題