我正在构建一个经历了几个步骤的Akka Streams应用程序。有一个特定步骤产生0或更多结果,事先不知道有多少结果。每个结果都必须异步处理(通过相同类型的组件),最后必须合并所有结果。
我应该如何在Akka Streams中对此进行建模?我注意到GraphDsl有一个Broadcast元素,可以让你为扇形建模,但这似乎只有在预先知道出口数量时才有可能。 在Akka Streams中有没有像广播这样的东西,但是那些粉丝会出现在动态数量的网点上?
答案 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