Akka remoting - 要求routee不回答

时间:2015-12-25 10:31:32

标签: scala playframework akka remoting

我正在尝试ask某个已经在SmallestMailboxPool远程创建的演员,但我似乎从来没有得到过回应。我的感觉是,这是因为我将消息发送到Router,但Routee是响应的演员 - 不知道Akka的确切内部问题,我可以想象答案必须是与发送邮件的位置相同。另一方面,这似乎是如此简陋,以至于我无法想象它会起作用。

我正在使用Play framework 2.3.x和Akka remote 2.3.4

演员设置 我在这些机器上有2台机器和2名演员。我会尽量保持这个例子尽可能简短。

机器A /演员A

实际的问题是在机器A上启动的,我添加了一些println语句来显示演员地址。代码如下。

class ActorA(remoteActor: ActorRef) extends Actor with ActorLogging {
    ...
    def receive() = {
        case a: String => {
            println("Remote actor: " + remoteActor)
            println("Self: " + self)
            // This is where I get a timeout because I never get a reply
            Await.result((remoteActor ? a), timeout.duration)
        }
    }
}

我在机器A上获得的输出如下:

Remote actor: Actor[akka.tcp://application@192.168.0.101:2552/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3#-1920529606]
Self: Actor[akka://application/user/9df0190a-11fb-438c-9124-4869d015fc4d#-867250738]

请注意,我传递给ActorA的ActorRef(称为remoteActor)是我在机器B上创建的val actorRef(见下文),具有MailboxPool。

机器B /演员B

在机器B上,我有一个在SmallestMailboxPool中创建的Actor B,并从Actor A(通过路由器)收到消息,之后它会回复。

创作如下:

// Creation of the mailbox/Router
val actorRef = Akka.system.actorOf(
    SmallestMailboxPool(1).props(
        // sourceActor is the actorRef of Actor A, living on machine A
        Props(ActorB, sourceActor)
    ),
    name = java.util.UUID.randomUUID.toString
)
println("Mailbox is: " + actorRef)

实际的演员B执行以下操作:

class ActorB(sourceActor: ActorRef) extends Actor with ActorLogging {
    println("I am: " + self)
    def receive() = {
        case a: String => {
            println("I got data from " + sender)
            println("Sending it back to: " + sourceActor)
            sourceActor ! d
        }
    }
}

我从演员B得到的是以下版画线:

Mailbox is Actor[akka://application/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3#-1920529606]
I am Actor[akka://application/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3/$a#46262703]
I got data from Actor[akka.tcp://application@192.168.0.132:2552/temp/$e]
I am sending it back to: Actor[akka.tcp://application@192.168.0.132:2552/user/9df0190a-11fb-438c-9124-4869d015fc4d#-867250738]

所以我得不到的是为什么来自ActorA的演员地址在ActorB的一边显示为temp/$e。还可以看出,ActorB从ActorA获取消息,实际上它将其发送到路由器。然后ActorB正确地尝试回复给ActorA,但它总是会超时 - 这是因为ActorB有一个与路由器/邮箱不同的ActorRef /地址吗?我还尝试发送回sender而不是参数给定的sourceActor,但无济于事。

我知道我可以向Mailbox询问其所有Routees并直接向他们发送请求(尚未尝试过),但这违背了MailboxPool的全部目的。 编辑:试过这个,也没办法

修改

整个故事中最奇怪的是,如果我在机器A上创建ActorB(例如,不是远程),一切正常 - 我可以问路由器的ActorRef我得到了一个合适的答复。一旦在机器B上创建ActorB,我就再也没有得到回复。我还试图了解如果我只是tell ActorB会发生什么情况并继续ActorA而不关心结果。然后会发生什么呢?我ActorB获取应该是我对原始提问的回复的消息... ActorB因此完全有能力发送回{{ 1}}但由于某种原因,Akka不会用它来回复我原来的问题......

1 个答案:

答案 0 :(得分:0)

我设法让它发挥作用。事实证明我正在将ActorRef传递给它应该发送给它的ActorB,但是在ActorA的提问时间,似乎Akka制作了一些真正需要从ActorB发送的临时演员(即我可以& #39; t只发送给ActorA的ActorRef,我将其传递给ActorB并存储在前面)。使用sender对我来说是一个修复。 (虽然我仍然感到困惑,为什么sender实际上不是我的演员A)。

我的实际用例太复杂了,无法在SO上分享,但我为一些感兴趣的人做了一个小例子(这个问题不会发生 - 一切正常):https://github.com/ErikTromp/AkkaRemoteAskTest。它也使用了Play的Iteratee库,因为这也是我用例的一部分。