Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 问模式是否适用于Akka IO演员?_Scala_Akka - Fatal编程技术网

Scala 问模式是否适用于Akka IO演员?

Scala 问模式是否适用于Akka IO演员?,scala,akka,Scala,Akka,假设我有一个IO Actor连接,能够通过TCP发送和接收消息。在我的演员中,我要求连接的另一方做出回应: connection.ask(ByteString("stuff")).collect { case Received(response) => log.debug(response.utf8String) } 使用此代码,ask future超时,而包含参与者接收ask模式之外的原始消息 你能在Akka IO演员身上使用ask模式吗?如果没有,为什么不呢?我不知道详细

假设我有一个IO Actor
连接
,能够通过TCP发送和接收消息。在我的演员中,我要求连接的另一方做出回应:

 connection.ask(ByteString("stuff")).collect {
    case Received(response) => log.debug(response.utf8String)
 }
使用此代码,ask future超时,而包含参与者接收ask模式之外的原始消息


你能在Akka IO演员身上使用ask模式吗?如果没有,为什么不呢?

我不知道详细的体系结构,但下面是我如何向自己解释的:

Akka IO连接器角色的问题在于它们不能以请求-响应方式工作。如果你仔细想想,这是有道理的,因为TCP不是一个请求-响应协议。TCP甚至没有消息的概念。从程序员的角度来看,TCP连接只是一对连续的字节流——每个方向一个。就这样

Akka IO是网络协议之上的最小参与者层,因此它模仿这种行为也就不足为奇了。当TCP参与者从网络接收到一些数据时,它只知道一件事——它应该向最初发送
Connect
消息的参与者发送
Received
消息。这就是全部。它不知道从网络接收到的数据与您先前发送的数据有什么关联

除此之外,
ask
模式仅在以下假设下工作:
A
向某个参与者发送消息时,它将通过将消息准确地发送给
A
的发送者来响应
B
。我们已经知道,TCP actor不会这样做——它只是将所有内容发送给原始
Connect
消息的发送者

之所以需要这种假设,是因为
ask
模式实际上创建了某种“幻影”参与者,该参与者被设置为使用
ask
发送的消息的发送者。然后,这个“幻影”参与者将接收响应并调用
将来注册的所有回调。请注意,这些回调是完全独立于发送参与者调用的,也就是说,它们可能与发送参与者并发运行


因此,我最终得出结论,像这样使用的
ask
模式对Akka IO不起作用,因为对于这样的抽象来说,它的级别太低了。如果您仍然需要它,您需要在Akka IO之上创建自己的抽象层,例如,一些简单的中间参与者,涵盖TCP连接器参与者并实现请求-响应行为。

作为@ghik答案的附加参考,这里大致介绍了我如何创建一个中间参与者,以便在其余参与者上启用IO的ask模式

class IOAskHandlerActor(address: InetSocketAddress) extends Actor {
   override def receive = {
      // Connection setup code omitted    
      case Connected(remote, local) =>
         // other code omitted
         context become latch(sender())
   }

   def latch(connection: ActorRef): Receive = {
      case outgoing =>
         context become receiving(connection, sender())
         connection ! MySerializer.write(outgoing)
   }

   def receiving(connection: ActorRef, asker: ActorRef): Receive = {
      case Received(incoming) =>
         context become latch(connection)
         asker ! MySerializer.read(incoming)
   }
}
此类实例可以
ask
ed以获得响应。注意,我只对一个同时询问者(这是我的用例)进行了测试,这可能不适用于多个询问者