【问题标题】:Akka remoting - asking routee doesn't return answerAkka 远程处理 - 询问 routee 不返回答案
【发布时间】:2015-12-25 10:31:31
【问题描述】:

我正在尝试向SmallestMailboxPool 中远程创建的演员发送ask 的内容,但我似乎从未得到回应。我的感觉是,这是因为我将消息发送到Router,但Routee 是正在响应的演员 - 不知道 Akka 询问的确切内部情况,我可以想象回复必须与 where 相同消息被发送到。另一方面,这似乎太简陋了,我无法想象它不会起作用。

我正在使用 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 上,我有一个 Actor B,它在 SmallestMailboxPool 中创建,并从 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)

实际的 Actor 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 获取消息,ActorA 实际将消息发送到 Router。 ActorB 然后正确地尝试回复 ActorA,但它总是超时 - 这是因为 ActorB 的 ActorRef/地址与路由器/邮箱不同吗?我也尝试发回sender,而不是给定参数的sourceActor,但无济于事。

我知道我可以向邮箱询问其所有路由并直接向他们发送询问(尚未尝试过),但这违背了 MailboxPool 的全部目的。 编辑:试过了,也没用

编辑:

整个故事中最奇怪的是,如果我在机器 A 上创建 ActorB(例如,不是远程),一切正常 - 我可以询问路由器的 ActorRef,我得到了正确的答复。在机器 B 上创建 ActorB 后,我再也没有收到回复。我还试图看看如果我只是 tell ActorB 并继续 ActorA 而不关心结果会发生什么。然后发生的事情是我确实ActorB 收到消息,这应该是我对原始问题的回应......因此ActorB 完全能够发送回ActorA 但对于某些人原因,Akka 不会用它来回答我原来的问题...

【问题讨论】:

  • 您能否提供生成您传递给 ActorA 的 ActorRef 的代码?另外,remoteGenerator 是什么?
  • 我修正了错字,remoteGenerator 是 remoteActor。我还添加了用于从中获取 remoteActor 的代码(我传递给 ActorA 的 ActorRef) - 这是我在机器 B 上执行的 val actorRef = ... 的结果
  • 您能否说明sourceActorremoteActor 是如何创建的?即val sourceActor = ...val remoteActor = ...

标签: scala playframework akka remoting


【解决方案1】:

我设法让它工作。原来我正在将一个 ActorRef 传递给它应该发送到的 ActorB,但是在来自 ActorA 的询问时间,似乎 Akka 制作了某种实际上需要从 ActorB 发送到的临时演员(即我可以'不仅仅是发送到我传递给 ActorB 并在之前存储的 ActorA 的 ActorRef)。使用sender 对我来说是一个修复。 (虽然我还是很疑惑为什么sender实际上不是我的ActorA)。

我的实际用例过于复杂,无法在 SO 上分享,但我为感兴趣的人做了一个小示例(没有出现此问题 - 一切正常):https://github.com/ErikTromp/AkkaRemoteAskTest。它也使用 Play 的 Iteratee 库,因为这也是我的用例的一部分。

【讨论】:

    猜你喜欢
    • 2016-05-28
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多