Scala 如何使用akka流中的mapAsync使用分组子流
我需要做一些真正类似的事情 我的问题是,我有一个未知数量的组,如果mapAsync的并行数小于我得到的组数,那么在最后一个接收器中会出错 拆毁 SynchronousFileLink(/Users/sam/dev/projects/akka streams/target/log ERROR.txt) 由于上游错误 (akka.stream.impl.StreamSubscriptionTimeoutSupport$$anon$2) 我试图在AkkAsvs模式指南中提出一个中间缓冲区。Scala 如何使用akka流中的mapAsync使用分组子流,scala,stream,akka-stream,Scala,Stream,Akka Stream,我需要做一些真正类似的事情 我的问题是,我有一个未知数量的组,如果mapAsync的并行数小于我得到的组数,那么在最后一个接收器中会出错 拆毁 SynchronousFileLink(/Users/sam/dev/projects/akka streams/target/log ERROR.txt) 由于上游错误 (akka.stream.impl.StreamSubscriptionTimeoutSupport$$anon$2) 我试图在AkkAsvs模式指南中提出一个中间缓冲区。 但同样的结
但同样的结果扩展了jrudolph的评论,这是完全正确的 在此实例中,不需要
mapsync
。作为一个基本示例,假设您有一个元组源
import akka.stream.scaladsl.{Source, Sink}
def data() = List(("foo", 1),
("foo", 2),
("bar", 1),
("foo", 3),
("bar", 2))
val originalSource = Source(data)
然后,您可以执行groupBy来创建
每一个分组的源都可以通过一个映射来并行处理,无需任何花哨的东西。以下是在独立流中汇总每个分组的示例:
import akka.actor.ActorSystem
import akka.stream.ACtorMaterializer
implicit val actorSystem = ActorSystem()
implicit val mat = ActorMaterializer()
import actorSystem.dispatcher
def getValues(tuple : (String, Int)) = tuple._2
//does not have to be a def, we can re-use the same sink over-and-over
val sumSink = Sink.fold[Int,Int](0)(_ + _)
//a Source of (String, Future[Int])
val sumSource =
groupedSource map { case (id, src) =>
id -> {src map getValues runWith sumSink} //calculate sum in independent stream
}
现在所有的“foo”
数字与所有的“bar”
数字并行相加
mapsync
用于当您有一个返回Future[T]
的封装函数,并且您试图发出T
时;你的问题不是这样的。此外,mapAsync涉及的不是…我想知道使用mapAsync
是否有任何用途?如果只使用map
会发生什么?使用map时,组不会以并行/异步方式使用,这是我想要的行为。我认为这是一个误解。所有的组都由一个Source[Something]
表示(在groupBy
之后,您有一个Source[Source[Something]
,对吗?)。因此,在映射
(foreach
也应该工作)中,您需要做的唯一一件事就是运行子流,这是一个异步操作。然后子流将自行运行,并且您的映射
元素将可以自由地接受下一个源[Something]
。现在akka流已与akka流合并,并且源语义的源已替换为子流,一个人怎样才能完成类似的行为?@AlphaGeek我注意到groupBy功能几个月前发生了变化。cookbook有一个基于新的子流方法的更新示例:@RamonJRomeroyVigil cookbook没有解释它。他们使用reduce,如果我们在每个子流中都有项目的竖梃,这是不可行的。我(也是作者)想要的是每组获得Source
。我们将如何做到这一点?是否对此有过解决方案?@Zee不幸的是,子流的新实现没有传递与子流相关的密钥。因此,我不知道如何生成问题中要求的输出。。。
def getID(tuple : (String, Int)) = tuple._1
//a Source of (String, Source[(String, Int),_])
val groupedSource = originalSource groupBy getID
import akka.actor.ActorSystem
import akka.stream.ACtorMaterializer
implicit val actorSystem = ActorSystem()
implicit val mat = ActorMaterializer()
import actorSystem.dispatcher
def getValues(tuple : (String, Int)) = tuple._2
//does not have to be a def, we can re-use the same sink over-and-over
val sumSink = Sink.fold[Int,Int](0)(_ + _)
//a Source of (String, Future[Int])
val sumSource =
groupedSource map { case (id, src) =>
id -> {src map getValues runWith sumSink} //calculate sum in independent stream
}