2017-08-16 140 views
0

我有兩個演員A和B. 控制器向演員A發送請求。現在演員A返回類型爲Try[AbcResponse]的響應。 AbcResponse這裏是一個案例類。 基於某種邏輯的Actor A可能會直接返回此響應,或者可能會使用ask有條件地調用另一個actor B.在操縱B的響應之後,它會將類型爲Try[AbcResponse]的響應發送給控制器。Scala:條件演員鏈接

那麼我應該怎樣在我的演員A中處理這種情況。我不想在我的演員A中等待,因爲這會浪費線程池並導致系統速度下降。我如何有效地處理這個問題?

回答

0

您可以將消息中的發件人參考傳遞給演員B,並將pipe演員B的響應傳遞給self。很顯然,在它的響應演員B將不得不通過這個參考回到演員A.

import akka.pattern.{ask, pipe} 

case class MsgToActorB(..., target: ActorRef) 
case class ResponseFromActorB(..., target: ActorRef) 

class ActorA extends Actor { 
    def receive = { 
    case r: Request => 
     val s = sender 
     implicit val timeout = Timeout(5 seconds) 
     // do something with the request 
     if (someCondition) 
     s ! Try(AbcResponse(...)) 
     else 
     (actorB ? MsgToActorB(..., s)).mapTo[ResponseFromActorB].pipeTo(self) 

    case ResponseFromActorB(..., target) => 
     // do something with the response from B and send a response to the original sender 
     target ! Try(AbcResponse(...)) 
    } 
} 

雖然上述方法是安全的,它會是簡單的不使用ask,如下圖所示。如果您必須使用ask,並且如果演員B在處理來自演員A的消息時處於阻塞狀態,則請考慮按照here中所述配置單獨的調度器。

def receive = { 
    case r: Request => 
    val s = sender 
    // do something with the request 
    if (someCondition) 
     s ! Try(AbcResponse(...)) 
    else 
     actorB ! MsgToActorB(..., s) 

    case ResponseFromActorB(..., target) => 
    // do something with the response from B and send a response to the original sender 
    target ! Try(AbcResponse(...)) 
} 
+0

在這種情況下,在使用ask調用actor B後,在演員本身中進行回調是不好的? – Sidhant

+0

@Sidhant:用'ask'使用'mapTo'和'pipeTo'(不是回調函數)是一種常見模式,正如[here]所述(http://doc.akka.io/docs/akka/2.5.4 /scala/actors.html#ask-send-and-receive-future)以及文檔的其他部分。 – chunjef