简体   繁体   English

使用Akka Streams动态扇出

[英]Dynamic fan out with Akka Streams

I am building an Akka Streams application that goes through a couple of steps. 我正在构建一个经历了几个步骤的Akka Streams应用程序。 There is one particular step that produces 0 or more results, it is not known in advance how many there are. 有一个特定步骤产生0或更多结果,事先不知道有多少结果。 Each of the results has to be processed asynchronously (by the same kind of component) and finally all the results have to be merged. 每个结果都必须异步处理(通过相同类型的组件),最后必须合并所有结果。

How should I model this in Akka Streams? 我应该如何在Akka Streams中对此进行建模? I noticed that GraphDsl has a Broadcast element that lets you model a fan out, however this seems to be only possible when the number of outlets is know in advance. 我注意到GraphDsl有一个Broadcast元素,可以让你为扇形建模,但这似乎只有在预先知道出口数量时才有可能。 Is there a way in Akka Streams to have something like Broadcast but that fans out to a dynamic number of outlets? 在Akka Streams中有没有办法让广播有一些东西,但那些粉丝会出现在动态数量的网点上?

Check out Hubs in this page: https://doc.akka.io/docs/akka/current/stream/stream-dynamic.html?language=scala 查看此页面中的中心: https//doc.akka.io/docs/akka/current/stream/stream-dynamic.html? language = scala

There are many cases when consumers or producers of a certain service (represented as a Sink, Source, or possibly Flow) are dynamic and not known in advance. 在许多情况下,某个服务的消费者或生产者(表示为接收器,源或可能的流)是动态的并且事先不知道。 The Graph DSL does not allow to represent this, all connections of the graph must be known in advance and must be connected upfront. Graph DSL不允许表示这一点,图表的所有连接必须事先知道并且必须预先连接。 To allow dynamic fan-in and fan-out streaming, the Hubs should be used. 要允许动态扇入和扇出流,应使用集线器。

It turns out that mapConcat does what I want. 事实证明mapConcat做了我想要的。 Here's a POC: 这是一个POC:

package streams

import scala.concurrent._
import akka._
import akka.actor._
import akka.stream._
import akka.stream.scaladsl._
import scala.util.Random

object StreamsTest extends App {
  implicit val system = ActorSystem("TestSystem")
  implicit val materializer = ActorMaterializer()
  import system.dispatcher

  case class SplitRequest(s: String)

  def requestHandlerWithMultipleResults(request: SplitRequest): List[String] = 
   request.s.split(" ").toList

  def slowProcessingTask(s: String) =  {
    Thread.sleep(Random.nextInt(5000))
    s.toUpperCase
  }

  val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
    import GraphDSL.Implicits._

    val source: Source[String, NotUsed] = Source(List(SplitRequest("january february march april may")))
      .mapConcat(requestHandlerWithMultipleResults)
      .mapAsyncUnordered(5)(s => Future(slowProcessingTask(s)))

    val sink = Sink.foreach(println)

    source ~> sink

    ClosedShape
  })

  g.run()
}

Output, eg: 输出,例如:

MAY
JANUARY
FEBRUARY
MARCH
APRIL

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

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