简体   繁体   English

Akka远程处理-询问路线不会返回答案

[英]Akka remoting - asking routee doesn't return answer

I am trying to ask something to an actor that has been created remotely in a SmallestMailboxPool but I never seem to get a response. 我正在尝试向在SmallestMailboxPool远程创建的演员ask一些问题,但是我似乎从未得到回应。 My feeling is that this is because I send the message to the Router , but the Routee is the actor that is responding - not knowing the exact internals of Akka's ask, I can imagine that the replied must be the same as where the message was sent to. 我的感觉是,这是因为我将消息发送到Router ,但是Routee是正在响应的演员-不知道Akka询问的确切内部情况,我可以想象得到的答复必须与消息发送的地点相同至。 On the other hand, this seems so rudimentary that I cannot imagine it wouldn't work. 另一方面,这似乎太初级了,我无法想象它是行不通的。

I am using Play framework 2.3.x and Akka remote 2.3.4 我正在使用Play框架2.3.x和Akka远程2.3.4

Actor Setup I have 2 machines with 2 actors on these machines. 演员设置我有2台机器,这些机器上有2个演员。 I will try to keep the example as brief as possible. 我将尝试使示例尽可能简短。

Machine A/Actor A 机器A /演员A

The actual ask is being initiated on Machine A, I added some println statements to show actor addresses. 实际的询问是在机器A上启动的,我添加了一些println语句以显示参与者地址。 The code is as follows. 代码如下。

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)
        }
    }
}

The output I am getting on Machine A is the following: 我在机器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]

Note that the ActorRef I am passing on to ActorA (called remoteActor ), is the val actorRef that I create on Machine B (see below), having the MailboxPool. 需要注意的是ActorRef我传递到ActorA(称为remoteActor ),是val actorRef我在机器B(见下文),具有MailboxPool创建。

Machine B/Actor B 机器B /演员B

On Machine B, I have an Actor B that is created in a SmallestMailboxPool and recieves the message from Actor A (via the Router) after which it replies. 在计算机B上,我有一个Actor B,该Actor B在SmallestMailboxPool中创建,并从Actor A(通过路由器)接收消息,然后答复。

The creation is as follows: 创建如下:

// 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)

The actual Actor B does the following: 实际的演员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
        }
    }
}

What I am getting from Actor B is the following printlines: 我从演员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]

So what I don't get is why the actor address from ActorA appears as temp/$e on ActorB's side. 所以我不明白的是为什么ActorA的actor地址在ActorB的一侧显示为temp/$e As can also be seen, ActorB gets the message from ActorA, which actually sends it to the Router. 可以看出,ActorB从ActorA获取消息,该消息实际上将其发送到路由器。 ActorB then rightfully tries to reply back to ActorA, but it always gets a timeout - is this because ActorB has a different ActorRef/address than the Router/Mailbox? 然后,ActorB会正确地尝试回复给ActorA,但它总是会超时-这是因为ActorB的ActorRef /地址与路由器/邮箱的地址不同吗? I also tried sending back to sender instead of the parameter-given sourceActor , but to no avail. 我也尝试发送回sender而不是参数给定的sourceActor ,但无济于事。

I know I can ask the Mailbox for all its Routees and send an ask directly to them (haven't tried this yet), but that defies the whole purpose of a MailboxPool. 我知道我可以向邮箱询问所有路由,然后直接向他们发送一个询问(尚未尝试过),但这违背了MailboxPool的全部目的。 EDIT : Tried this, didn't work either 编辑 :尝试过这个,也没有用

EDIT: 编辑:

The weirdest of this entire story, is that if I create ActorB on machine A (eg. not remotely), everything works just fine - I can ask the Router's ActorRef and I get a proper reply. 整个故事中最怪异的是,如果我在机器A上创建ActorB (例如,不是远程创建),那么一切都可以正常工作-我可以询问路由器的ActorRef并得到适当的答复。 As soon as ActorB is created on machine B, I never get a reply anymore. 一旦在机器B上创建了ActorB ,我就再也ActorB回复。 I also tried to see what happens if I just tell ActorB and continue in ActorA without caring for the result. 我还试图看看如果我只是tell ActorB并继续ActorA而又不关心结果的话会发生什么。 What happens then is that I do get the message from ActorB that should be my response to the original ask... ActorB is hence perfectly capable of sending back to ActorA but for some reason, Akka won't use it as the reply to my original ask... 然后发生的是,我确实ActorB收到了消息,该消息应该是我对原始询问的答复...因此, ActorB完全有能力发回给ActorA但由于某种原因,Akka不会将其用作对我的答复。原来问...

I managed to get it work. 我设法使它起作用。 Turns out I was passing around an ActorRef to ActorB to which it was supposed to send, but at ask-time from ActorA, it seems like Akka makes some sort of temp actor that actually needs to be sent to from ActorB (ie. I can't just send to the ActorRef of ActorA that I passed on to ActorB and stored earlier). 原来我正在将ActorRef传递给应该发送给ActorB的ActorRef,但是在从ActorA询问时,似乎Akka确实需要某种临时演员,实际上需要从ActorB发送给它(即,我可以不只是发送给我传递给ActorB并在更早之前存储的ActorA的ActorRef)。 Using sender was a fix for me. 使用sender对我来说是一个解决方法。 (Although I am still puzzled why sender was actually not my ActorA). (尽管我仍然感到困惑,为什么sender实际上不是我的ActorA)。

My actual use case is far too complex to share on SO, but I made a small example (where this problem doesn't occur - everything works) for people interested: https://github.com/ErikTromp/AkkaRemoteAskTest . 我的实际用例太复杂了,无法在SO上共享,但是我为感兴趣的人提供了一个小例子(不会发生此问题-一切正常): https : //github.com/ErikTromp/AkkaRemoteAskTest It uses Play's Iteratee library too, since that is part of my use case too. 它也使用Play的Iteratee库,因为这也是我的用例的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM