13

这是一个设计问题;

假设我有一棵执行大量处理的演员树。处理由客户端/连接参与者启动(即树是服务器)。最终,客户端参与者想要一个响应。即我有一个看起来像这样的演员系统。

    ActorA  <---reqData--- Client_Actor
       | msgA                    /|\                      
      \|/                         |                 
    ActorB                        |                  
  msgB |  \ msgD                  | 
      \|/  \/                     | 
    ActorC  ActorD---------msgY-->|
       |_____________msgX_________|

客户端系统想要的响应是叶参与者(即ActorC和/或ActorD)的输出。树中的这些参与者可能正在与外部系统交互。这棵树可能是一组预定义的可能路由的actor(即Client_actor只有一个actorref 指向actor 树的根ActorA)。

问题是管理将响应(msgX&/or msgY)从最终/叶参与者发送回客户端参与者的最佳模式是什么?

我可以想到以下选项;

  • 为每个连接客户端创建一个树,并让参与者跟踪发送者,当他们获得一个msgXor时msgY,将其发送回原始发送者 ref,以便消息通过树向上传递。即每个参与者将保留原始发件人的参考。
  • 以某种方式发送消息Client_Actor中的 refreqData并将其复制到树中使用的所有消息,以便叶参与者可以直接回复Client_actor... 这似乎是性能最高的选项。不知道如何做到这一点(我正在以某种方式在包含客户端actor ref 的消息案例类上考虑一个特征)......
  • 不知何故,基于通过树传递的消息中的唯一 id 查找客户端参与者或使用参与者选择(不确定这将如何与远程处理一起工作)......
  • 更好的东西...

仅供参考,我正在使用 Akka 2.2.1。

干杯!

4

3 回答 3

22

您可以使用该forward方法将消息从原始发件人转发到每个级别的子发件人。

在 Client_Actor 中:

actorA ! "hello"

在演员A中:

def receive = {
  case msg =>
    ???
    actorB forward msg
}

在演员 B 中:

def receive = {
  case msg =>
    ???
    actorC forward msg
}

在 ActorC 中:

def receive = {
  case msg =>
    ???
    sender ! "reply" // sender is Client_Actor!
}

在这种情况下,消息的 'sender' 字段永远不会改变,所以 ActorC 会回复原来的 Client_Actor!

tell您可以使用允许您指定发件人的方法变体进一步扩展它:

destinationActor.tell("my message", someSenderActor);
于 2013-10-10T17:08:27.313 回答
1

最简单的方法是将带有 ref 的消息发送到源 Client_Actor

Client
 sendMsg(Client to, Client resultTo)

Client_Actor
 req_data(Client to){
   sendMsg(to, this);
 }

这是一个不错的选择,如果您不知道哪个客户有原始海报的结果,哪个没有。

如果您知道这一点并且 Client_Actor 只有一个(就像我们有一棵树,而这些并且只有 LEAFS 将始终响应且只有 Client_Actor),您可以执行以下操作:

Client
  register_actor(Client actor){this.actor = actor;}
  call_actor(){ this.actor.sendMsg(); }
于 2013-10-10T17:07:48.230 回答
1

对于这样的情况,我写了一个叫做ResponseAggregator. 它是Actor根据需要实例化的(而不是作为持久的单个实例),将目标作为参数ActorRef,任意key(如果单个目标由多个聚合器提供,则区分聚合器),完成谓词,接收到的Seq[Any]持有响应到目前为止,由聚合器返回true如果这些响应表示聚合过程的完成和超时值。聚合器接受并收集传入消息,直到谓词返回 true 或超时到期。一旦聚合完成(包括由于超时),所有接收到的消息都会连同一个指示聚合是否超时的标志一起发送到目的地。

代码有点太大,无法包含在此处,并且不是开源的。

为此,通过系统传播的消息必须带有ActorRefs 指示响应消息将发送给谁(我很少设计只回复 的参与者sender)。

我经常将replyTo消息值的字段定义为ActorRef*然后使用我的MulticastActor类,它启用了!*“发送到多个收件人”操作符。这在消息构造中具有语法简洁的优点(与使用 Option[ActorRef] 或 Seq[ActorRef] 相比)并且具有相同的开销(需要构造一些东西来捕获对actor ref 或 refs 的回复)。

无论如何,有了这些东西,您可以设置非常灵活的路由拓扑。

于 2013-10-10T17:41:55.123 回答