2

我正在使用 Play 2.5。我正在使用 Websocket Actor 将消息发送到 Routes Actor。但是,当在 Routes 上收到 msg 时,sender() 方法返回 Routes 本身而不是那个 Websocket 参与者。

申请如下

@Singleton
class Application @Inject()(implicit val system: ActorSystem,
                            implicit val wsClient: WSClient,
                            implicit val config: Configuration,
                            implicit val materializer: Materializer) extends Controller {
...
  lazy val routesActor = system.actorOf(Props(classOf[RoutesActor]), "routes")

  def ws = WebSocket.accept[JsValue, JsValue] { request =>
    ActorFlow.actorRef(out => UserActor.props(out)(routesActor))
  }

...
}

用户演员:

class UserActor(out: ActorRef)(implicit val RoutesActor: ActorRef) extends Actor with ActorLogging {

  def receive() = {
    case json: JsValue => {
      val parsedQuery = parseQuery(json)
      cachesActor ! (parsedQuery, self)
      log.info("this user is:" + self)
    }
  }

路线演员

class RoutesActor extends Actor with ActorLogging {
  def receive = {
    case (q: ParsedQuery, out: ActorRef) => {
      log.info("Routes:" + self + " get query from : " + sender() + " actually is:" + out)
    }
  }
}

log.info 打印了以下行:

[info] a.RoutesActor - Routes:Actor[akka://application/user/routes#854844162] 获取查询来自:Actor[akka://application/user/routes#854844162] 实际上是:Actor[akka://应用程序/用户/$b/flowActor#-75193340]

如您所见, sender() 指向自身而不是 flowActor。因此,我不能使用 sender() 来回复消息。这让我很困惑。有谁知道这里出了什么问题?

4

1 回答 1

2

tell 的签名是def !(message: Any)(implicit sender: ActorRef): Unit,因此消息的发送者通过隐式参数获取。当您从 中发送消息时UserActor,这implicit val RoutesActor: ActorRef是定义为类参数的 。

如果要将UserActor用作发送者,请从参数列表中删除隐式关键字或self显式提供作为发送者:cachesActor.tell((parsedQuery, self), self)

如果您想使用原始发件人,也就是sender()中的那个UserActor,您可以forward改用:cachesActor.forward((parsedQuery, self))。这将显式使用context.sender()而不是隐式RoutesActor作为消息的发送者。

于 2016-04-01T07:37:39.100 回答