map和mapAsync之间的区别

时间:2016-02-02 06:20:37

标签: scala akka-stream

任何人都可以解释一下地图和mapAsync w.r.t AKKA流之间的区别吗? In the documentation据说

  

涉及外部非流的流转换和副作用   可以使用mapAsync或mapAsyncUnordered

执行基于服务的服务

为什么我们不能简单地在这里映射?我假设Flow,Source,Sink都是Monadic,因此map应该工作得很好w.r.t延迟性质这些?

1 个答案:

答案 0 :(得分:43)

<强>特征

差异最好在signatures中突出显示:Flow.map接受一个返回类型T的函数,而Flow.mapAsync接受一个返回类型{{的函数1}}。

实践示例

例如,假设我们有一个函数,它根据用户ID在数据库中查询用户的全名:

Future[T]

给定type UserID = String type FullName = String val databaseLookup : UserID => FullName = ??? //implementation unimportant Source个值的{* 1}},我们可以在流中使用UserID来查询数据库并将全名打印到控制台:

Flow.map

此方法的一个限制是此流只能一次进行1 db查询。此串行查询将是一个“瓶颈”,可能会阻止我们的流中的最大吞吐量。

我们可以尝试使用val userIDSource : Source[UserID, _] = ??? val stream = userIDSource.via(Flow[UserID].map(databaseLookup)) .to(Sink.foreach[FullName](println)) .run()

通过并发查询来提高性能
Future

这个简单的附录的问题是我们已经有效地消除了背压。

Sink只是拉入未来并添加def concurrentDBLookup(userID : UserID) : Future[FullName] = Future { databaseLookup(userID) } val concurrentStream = userIDSource.via(Flow[UserID].map(concurrentDBLookup)) .to(Sink.foreach[Future[FullName]](_ foreach println)) .run() ,与数据库查询相比,它相对较快。该流将持续将需求传播到源并在foreach println内产生更多的期货。因此,并发运行Flow.map的数量没有限制。不受干扰的并行查询最终会使数据库过载。

databaseLookup救援;我们可以同时进行数据库访问,同时限制同时查找的数量:

Flow.mapAsync

另请注意,val maxLookupCount = 10 val maxLookupConcurrentStream = userIDSource.via(Flow[UserID].mapAsync(maxLookupCount)(concurrentDBLookup)) .to(Sink.foreach[FullName](println)) .run() 变得更简单,不再需要Sink.foreach而只需Future[FullName]

无序异步地图

如果不需要维护UserID到FullNames的顺序排序,那么您可以使用FullName。例如:您只需要将所有名称打印到控制台,但不关心它们的打印顺序。