2017-08-16 70 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