Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.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溪流-分流至多个水源_Scala_Akka_Akka Stream - Fatal编程技术网

Scala Akka溪流-分流至多个水源

Scala Akka溪流-分流至多个水源,scala,akka,akka-stream,Scala,Akka,Akka Stream,我在Akka流中有一个TCP连接,它在一个接收器中结束。现在所有的信息都进入一个接收器。我想在给定某个函数的情况下,将流拆分为未知数量的汇 用例如下所示,从TCP连接中,我得到了类似于List[DeltaValue]的连续流,现在我想为每个DeltaValue.id创建一个ActorLink,这样我就可以连续地为每个DeltaValue.id累积和实现行为。我发现这是流处理中的一个标准用例,但我找不到Akka流的好例子 这就是我现在拥有的: def connect(): ActorRef = t

我在Akka流中有一个TCP连接,它在一个接收器中结束。现在所有的信息都进入一个接收器。我想在给定某个函数的情况下,将流拆分为未知数量的汇

用例如下所示,从TCP连接中,我得到了类似于
List[DeltaValue]
的连续流,现在我想为每个
DeltaValue.id
创建一个ActorLink,这样我就可以连续地为每个
DeltaValue.id
累积和实现行为。我发现这是流处理中的一个标准用例,但我找不到Akka流的好例子

这就是我现在拥有的:

def connect(): ActorRef = tcpConnection
    .//SOMEHOW SPLIT HERE and create a ReceiverActor for each message
    .to(Sink.actorRef(system.actorOf(ReceiverActor.props(), ReceiverActor.name), akka.Done))
    .run()
更新: 我现在有这个,不知道该怎么说,它感觉不太稳定,但应该可以工作:

  private def spawnActorOrSendMessage(m: ResponseMessage): Unit = {
    implicit val timeout = Timeout(FiniteDuration(1, TimeUnit.SECONDS))
    system.actorSelection("user/" + m.id.toString).resolveOne().onComplete {
      case Success(actorRef) => actorRef ! m
      case Failure(ex) => (system.actorOf(ReceiverActor.props(), m.id.toString)) ! m
    }
  }

  def connect(): ActorRef = tcpConnection
    .to(Sink.foreachParallel(10)(spawnActorOrSendMessage))
    .run()

事件流

您可以向流接收器中的ActorSystem发送消息,并分别让参与者订阅流

在流级别拆分

可以使用在流级别拆分流。政府有一个很好的例子

演员级拆分


您还可以与a结合使用,将消息广播给多个参与者。

以下应该是问题中更新内容的改进版本。主要的改进是将参与者保存在数据结构中,以避免对每个传入消息进行
actorSelection
解析

  case class DeltaValue(id: String, value: Double)

  val src: Source[DeltaValue, NotUsed] = ???

  src.runFold(Map[String, ActorRef]()){
    case (actors, elem) if actors.contains(elem.id) ⇒
      actors(elem.id) ! elem.value
      actors
    case (actors, elem) ⇒
      val newActor = system.actorOf(ReceiverActor.props(), ReceiverActor.name)
      newActor ! elem.value
      actors.updated(elem.id, newActor)
  }
请记住,当您将Akka流与裸演员集成时,您将失去背压支持。这就是为什么您应该尽可能在Akka Streams的边界内尝试并实现您的逻辑的原因之一。这并不总是可能的-例如,当需要远程处理时等

在您的情况下,您可以考虑使用<代码> GROPPB/<代码>和下面的示例通过求和来折叠每个子流的元素,只是为了给出一个想法:

  src.groupBy(maxSubstreams = Int.MaxValue, f = _.id)
    .fold("" → 0d) {
      case ((id, acc), delta) ⇒ id → delta.value + acc
    }
    .mergeSubstreams
    .runForeach(println)

增加了更多的内容这两种情况都要求我事先知道我需要多少演员,我已经在这个问题上提供了更多关于我在尝试什么的信息todo@user3139545更新了另一个备选方案,允许未知数量的订阅者…我也可以从我的sink actor中生成子actor并转发给他们,然而,这似乎是akka stream构建的支持,这样我就不必处理纯演员的所有额外操作。配分函数呢?听起来很完美,但找不到它的任何例子。这是一个很好的例子,在我的情况下,我无法控制发送TCP套接字,如果不能以与它产生相同的速率消耗,那么它将毫无用处,所以我猜背压对我没有任何帮助。