我正在尝试 ask
某个已经在 SmallestMailboxPool
远程创建的演员,但我似乎从来没有得到过回应 . 我的感觉是,这是因为我将消息发送到 Router
,但 Routee
是响应的演员 - 不知道Akka的确切内部工作 .
我正在使用Play framework 2.3.x和Akka remote 2.3.4
Actor Setup 我在这些机器上有两台机器,有两个演员 . 我会尽量保持这个例子尽可能简短 .
机器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]
请注意, ActorRef
我传递给ActorA(名为 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)
实际的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获取消息,实际上它将其发送到路由器 . 然后ActorB正确地尝试回复给ActorA,但它总是会超时 - 这是因为ActorB有一个与路由器/邮箱不同的ActorRef /地址吗?我也尝试发送回 sender
而不是参数给定 sourceActor
,但无济于事 .
我知道我可以向Mailbox询问其所有Routees并直接向他们发送请求(尚未尝试过),但这违背了MailboxPool的全部目的 . EDIT :试过这个,也没用
EDIT:
这整个故事中最奇怪的是,如果我在机器A上创建 ActorB
(例如,不是远程),一切正常 - 我可以问路由器的 ActorRef
并得到一个正确的答复 . 一旦在机器B上创建 ActorB
,我就再也没有得到回复 . 我也试着看看如果我只是 tell
ActorB
会发生什么,并继续在 ActorA
而不关心结果 . 接下来发生的事情是我 do 从 ActorB
获取的信息应该是我对原始问题的回复... ActorB
因此完全有能力发送回 ActorA
但由于某种原因,Akka不会将其用作对我的回复原问...
1 回答
我设法让它工作 . 事实证明我正在将ActorRef传递给它应该发送给它的ActorB,但是在ActorA的提问时间,似乎Akka制作了一些真正需要从ActorB发送的临时演员(即我可以我只是发送给ActorA的ActorRef,我将它传递给ActorB并存储在前面) . 使用
sender
对我来说是一个修复 . (虽然我仍然感到困惑,为什么sender
实际上不是我的演员A) .我的实际用例太复杂了,无法在SO上分享,但我为一些感兴趣的人做了一个小例子(这个问题没有发生 - 一切正常):https://github.com/ErikTromp/AkkaRemoteAskTest . 它也使用Play的Iteratee库,因为这也是我的用例的一部分 .