【问题标题】:Play 2.5 What is akka.stream.Materializer useful for?玩 2.5 akka.stream.Materializer 有什么用?
【发布时间】:2016-04-27 11:19:35
【问题描述】:

我最近开始使用Play 2.5,想知道这样做的目的是什么:

@Inject() (implicit val mat: Materializer)

我有几段代码无法正常工作并因此解决了这个问题,但我仍然看不到物化器在做什么。

谢谢

【问题讨论】:

  • Play 2.5 使用 Akka Streams 作为 ReactiveStreams 实现,因此需要物化器。见Streams Migration
  • 还有akka streams documentation 深入解释了物化器实际上是什么以及它的作用。
  • 这些“几段代码”在做什么?
  • 按实例:class A@Inject()(implicit val mat: Materializer, cache: CacheApi, wsClient: WSClient, configuration: play.api.Configuration) 在我做 Materializer 之前没有用。

标签: scala playframework


【解决方案1】:

物化意味着产生graph的结果

物化器使actors 执行图表以产生这些结果。

最简单的图形由提供元素的源和消耗元素的接收器组成。

这是一个提供整数范围的来源(在本例中,整数是我们的元素):

val source = Source(1 to 10)

这是一个接收器,它将从源中获取的所有整数相加:

val sink = Sink.fold[Int, Int](0)(_ + _)

我们连接 source 和 sink 得到一个图:

val graph = source.toMat(sink)(Keep.right)

请注意,没有计算,在我们的例子中,添加是在创建图形时执行的。 代码是declarative,图表描述了我们想要如何转换我们的数据,但实际执行计算是其他人的工作:图表是blueprints

现在,物化器呢?当我们运行图表时,物化器会采取行动:

implicit val materializer = ActorMaterializer()
val futureResult = graph.run()

当我们run()图表时,物化器获取图表并让actor执行图表中指定的数据转换;在本例中,就是整数相加。

将图表想象成建造房屋的蓝图可能会有所帮助,物化者就像看着蓝图的工头,告诉建造者如何根据蓝图实际建造房屋。这个类比中的建造者对应于 Akka 中的演员。

您的几段代码现在可以工作的原因是,通过物化器,您提供了一种执行图形的方法。 Graph 在 Akka HTTP 中大量使用,Play 将其用于 HTTP 请求和响应。

您在评论中提到的WSClient 使用图表来执行其请求,因此需要一个物化器。


以下是创建和运行图表的完整示例:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}

object Graphs extends App {
  // The start of our simple graph. It provides elements, integers in our case
  val source = Source(1 to 10)

  // The end of our graph. It processes the source's elements
  val sink = Sink.fold[Int, Int](0)(_ + _)

 /*
  * Connect source and sink.
  * Keep only the output values (i.e., the graph's right side).
  * Note that this is declarative: no result is computed until we run the graph.
  */
  val graph = source.toMat(sink)(Keep.right)

  // The system coordinates actors and provides threads for them
  implicit val actorSystem = ActorSystem()
  // The materializer makes actors execute graphs
  implicit val materializer = ActorMaterializer()

  // Running the graph means that the materializer assigns actors to execute
  // the graph from start (source) to end (sink)
  val futureResult = graph.run()

  // Use the actor system's execution context, which provides threads,
  // to print the result of running the graph
  implicit val executionContext = actorSystem.dispatcher
  futureResult.foreach(res => println(s"Result of running the graph: $res"))

  actorSystem.terminate().foreach(_ => println("System is shut down"))
}

把它放在你的build.sbt 中,让 Akka 的流库在你的代码中可用:

libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.5.19"

Here's more 在源和接收器上。

【讨论】:

  • 房子和建筑商的例子让我更清楚了!泰!
  • 还有一个问题:假设有一个 Play 项目,其中包含使用 Akka 流的各种类(例如,各种 MongoDB DAO),我们是否为每个类实例实例化一个新的物化器,或者我们可以只拥有一个可以共享吗?如果共享很好,我们将如何共享这样的物化器?
  • @ManabuTokunaga:我已经有一段时间没有使用 Scala 了,但我认为在类之间共享一个物化器是可行且合理的。至于如何共享materializer:可以将materializer作为构造函数参数传递给需要materializer的类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
相关资源
最近更新 更多