使用Akka Streams动态扇出

时间:2018-04-29 15:31:23

标签: akka akka-stream

我正在构建一个经历了几个步骤的Akka Streams应用程序。有一个特定步骤产生0或更多结果,事先不知道有多少结果。每个结果都必须异步处理(通过相同类型的组件),最后必须合并所有结果。

我应该如何在Akka Streams中对此进行建模?我注意到GraphDsl有一个Broadcast元素,可以让你为扇形建模,但这似乎只有在预先知道出口数量时才有可能。 在Akka Streams中有没有像广播这样的东西,但是那些粉丝会出现在动态数量的网点上?

2 个答案:

答案 0 :(得分:3)

在此页面中查看集线器https://doc.akka.io/docs/akka/current/stream/stream-dynamic.html?language=scala

  

在许多情况下,某个服务的消费者或生产者(表示为接收器,源或可能的流)是动态的并且事先不知道。 Graph DSL不允许表示这一点,图表的所有连接必须事先知道并且必须预先连接。为了允许动态扇入和扇出流,应该使用集线器。

答案 1 :(得分:1)

事实证明mapConcat符合我的要求。这是一个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()
}

输出,例如:

MAY
JANUARY
FEBRUARY
MARCH
APRIL