Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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 什么';在阿克卡等待一群演员回应是一个好办法吗?_Scala_Akka_Future - Fatal编程技术网

Scala 什么';在阿克卡等待一群演员回应是一个好办法吗?

Scala 什么';在阿克卡等待一群演员回应是一个好办法吗?,scala,akka,future,Scala,Akka,Future,在Akka中,我想向集群中的参与者发送一条“状态”消息,了解他们的状态。这些参与者可能处于各种健康状态,包括死亡/无法应对 我想等待一段时间,比如说10秒,然后继续处理我在那个时间限制内收到的任何结果。我不想让整个过程失败,因为1或2个出现问题,并且在10秒时没有响应/超时 我试过这个: object GetStats { def unapply(n: ActorRef )(implicit system: ActorSystem): Option[Future[Any]] = Try {

在Akka中,我想向集群中的参与者发送一条“状态”消息,了解他们的状态。这些参与者可能处于各种健康状态,包括死亡/无法应对

我想等待一段时间,比如说10秒,然后继续处理我在那个时间限制内收到的任何结果。我不想让整个过程失败,因为1或2个出现问题,并且在10秒时没有响应/超时

我试过这个:

object GetStats {
  def unapply(n: ActorRef )(implicit system: ActorSystem): Option[Future[Any]] = Try {
    implicit val t: Timeout = Timeout(10 seconds)
    n ? "A" 
  }.toOption
}
...
val z = List(a,b,c,d)  // where a-d are ActorRefs to nodes I want to status
val q = z.collect {
   case GetStats(s) => s
}
// OK, so here 'q' is a List[Future[Any]]
val allInverted = Future.sequence(q) // now we have Future[List[Any]]
val ok =  Await.result(allInverted, 10 seconds).asInstanceOf[List[String]]
println(ok)

此代码的问题在于,如果1个或多个没有响应,它似乎会抛出TimeoutException。然后,我无法获得返回的响应。

假设您真的需要每10秒收集至少部分统计信息-解决方案是将“无响应”转换为实际故障

要实现这一点,只需将
wait
timeout与ask的
implicit val t:timeout
相比增加一点。在此之后,您的futures itselves(从
返回)将提前失败。所以你可以告诉他们:

例如:

scala> class MyActor extends Actor{ def receive = {case 1 => sender ! 2; case _ =>}}
defined class MyActor

scala> val a = sys.actorOf(Props[MyActor])
a: akka.actor.ActorRef = Actor[akka://1/user/$c#1361310022]

scala> implicit val t: Timeout = Timeout(1 seconds)
t: akka.util.Timeout = Timeout(1 second)

scala> val l = List(a ? 1, a ? 100500).map(_.map(Some(_)).recover{case _ => None})
l: List[scala.concurrent.Future[Option[Any]]] = List(scala.concurrent.impl.Promise$DefaultPromise@7faaa183, scala.concurrent.impl.Promise$DefaultPromise@1b51e0f0)

scala> Await.result(Future.sequence(l).map(_.flatten), 3 seconds)
warning: there were 1 feature warning(s); re-run with -feature for details
res29: List[Any] = List(2)
如果您想知道哪个Future没有响应,请删除
flatten

接收部分响应应该足以持续收集统计数据,就好像一些工人参与者没有及时响应一样——下次它将使用实际数据进行响应,并且不会丢失任何数据。但您应该正确地处理worker的生命周期,并且不要在actor本身内部丢失任何数据(如果有关系的话)

如果超时原因只是系统压力过高-您可以考虑:

  • 工人专用池
  • 背压
  • 缓存输入请求(系统过载时)
如果此类超时的原因是某个远程存储,那么如果客户机已准备就绪,则部分响应是正确的处理方式。例如,WebUI可能会使用一些旋转的东西警告用户显示的数据可能未满。但别忘了不要用存储请求阻止参与者(未来可能会有帮助),或者至少不要将他们移动到separrate线程池

如果worker actor由于故障(如异常)而没有响应,您仍然可以从您的
重新启动前向发件人发送通知,这样您也可以从worker接收没有统计信息的原因。这里唯一的一件事-您应该检查发件人是否可用()

另外,我希望您不要在某个参与者内部执行
wait.result
——至少对于您的应用程序性能而言,不建议阻止某个参与者。在某些情况下,它甚至可能导致死锁或内存泄漏。所以wait应该放在系统外观的某个地方(若底层框架不支持未来)

因此,异步处理您的答案可能是有意义的(如果某个参与者没有响应,您仍然需要从失败中恢复答案):

//参与者:
val parent=发送方

for(列出为什么你不能问他们的主管?这里有很多我不知道的。最关键的是演员内部的等待。尝试后一种方式,但遇到了麻烦。在我的演员中,我有:for(列出1)忘了提到-你应该在将来使用一些永久链接到家长(见我的更新)-发件人正在动态更改;2)它不会帮助您解决超时问题-因此您仍然需要将超时转换为故障,如答案顶部所述,否则
for
中的代码块有时不会完成3)
implicit val timeout
应该小于
wait.timeout
for(2)。关于这一点:您可以使用“`”来标记代码块1*)每
生成一个合成的actor,它等待您的响应,因此每次新建
发送方时都会生成一个合成的actor。关于future异步执行,可能根本没有发送方,所以您应该在返回之前捕获它。
val parent=sender…
,正如我的更新中所写的那样。:-)就是这样。美丽的。
scala> class MyActor extends Actor{ def receive = {case 1 => sender ! 2; case _ =>}}
defined class MyActor

scala> val a = sys.actorOf(Props[MyActor])
a: akka.actor.ActorRef = Actor[akka://1/user/$c#1361310022]

scala> implicit val t: Timeout = Timeout(1 seconds)
t: akka.util.Timeout = Timeout(1 second)

scala> val l = List(a ? 1, a ? 100500).map(_.map(Some(_)).recover{case _ => None})
l: List[scala.concurrent.Future[Option[Any]]] = List(scala.concurrent.impl.Promise$DefaultPromise@7faaa183, scala.concurrent.impl.Promise$DefaultPromise@1b51e0f0)

scala> Await.result(Future.sequence(l).map(_.flatten), 3 seconds)
warning: there were 1 feature warning(s); re-run with -feature for details
res29: List[Any] = List(2)
 //actor:
 val parent = sender
 for(list <- Future.sequence(qfiltered)) {
     parent ! process(list)
 }

 //in sender (outside of the actors):
 Await(actor ? Get, 10 seconds)