Akka之Source相關API總結

weixin_34279579發表於2017-11-15

(1)apply[T](iterable: immutable.Iterable[T]): Source[T, NotUsed]
由Iterable建立Source。
例如:Source(Seq(1,2,3))
這類似於從迭代器開始, 但與此流的釋出者直接連線的每個訂閱者都將看到一個單獨的元素流 (總是從開始處開始), 而不管它們何時訂閱。

(2)fromIterator[T](f: () ⇒ Iterator[T]): Source[T, NotUsed]
從一個產生迭代器的函式開始一個新的Source。生成的元素流將繼續,直到迭代器執行為空或在評估next()方法時失敗。根據來自下游轉換步驟的需求,將元素從迭代器中拉出。
例如:

val iterator = Iterator.iterate(false)(!_)
//建立一個無限迭代器,重複地將給定的函式應用於先前的結果。
//第一個引數是初始值,第二個引數是將重複應用的函式。
Source.fromIterator(() ⇒ iterator)
        .grouped(10)
        .runWith(Sink.head)
        .futureValue

結果是
immutable.Seq(false, true, false, true, false, true, false, true, false, true)

(3)cycle[T](f: () ⇒ Iterator[T]): Source[T, NotUsed]
從給定的元素(由產生迭代器的函式得到)開始一個迴圈的Source。元素的生產流將無限地重複由函式引數提供的元素序列。
例如:

Source.cycle(() ⇒ List(1, 2, 3).iterator)
         .grouped(9)
         .runWith(Sink.head)
         .futureValue

結果是
immutable.Seq(1, 2, 3, 1, 2, 3, 1, 2, 3)

(4)fromGraph[T, M](g: Graph[SourceShape[T], M]): Source[T, M]
由source形狀(即只有一個出口)的圖建立Source。
例如:

val pairs = Source.fromGraph(GraphDSL.create() { implicit b =>
  import GraphDSL.Implicits._
 
  // prepare graph elements
  val zip = b.add(Zip[Int, Int]())
  def ints = Source.fromIterator(() => Iterator.from(1))
 
  // connect the graph
  ints.filter(_ % 2 != 0) ~> zip.in0
  ints.filter(_ % 2 == 0) ~> zip.in1
 
  // expose port
  SourceShape(zip.out)
})

(5)fromFuture[T](future: Future[T]): Source[T, NotUsed]
從給定的Future建立Source。當Future以成功值完成時(可能在物化Flow之前或者之後發生),流由一個元素組成。當Future以失敗完成時,流將終止並帶有一個failure。
例如:
Source.fromFuture(Future.successful("Hello Streams!"))

(6)fromCompletionStage[T](future: CompletionStage[T]): Source[T, NotUsed]
類似於Scala的Future建立Source,此處是由Java的CompletionStage建立Source。

(7)fromFutureSource[T, M](future: Future[Graph[SourceShape[T], M]]): Source[T, Future[M]]
由給定的future source形狀的圖建立Source。一旦給定的Future成功完成,則元素從非同步source流出。如果Future失敗,則流失敗。

(8)fromSourceCompletionStage[T, M](completion: CompletionStage[_ <: Graph[SourceShape[T], M]]): Source[T, CompletionStage[M]]
類似於fromFutureSource

(9)tick[T](initialDelay: FiniteDuration, interval: FiniteDuration, tick: T): Source[T, Cancellable]
元素定期以指定的間隔發出。
"滴答" 元素將被傳遞到請求任何元素的下游使用者。
如果使用者在生成滴答元素時沒有請求任何元素, 它以後將不會接收該滴答元素。它將在請求更多元素時立即接收新的滴答元素。
例如:
Source.tick(initialDelay = 2.second, interval = 1.second, "message!")

(10)single[T](element: T): Source[T, NotUsed]
由一個元素建立Source。
例如:Source.single("only one element")

(11)repeat[T](element: T): Source[T, NotUsed]
建立一個連續傳送給定元素的Source。
例如:

Source.repeat(42)
        .grouped(3)
        .runWith(Sink.head) 
        .futureValue

結果是:
immutable.Seq(42,42,42)

(12)unfold[S, E](s: S)(f: S ⇒ Option[(S, E)]): Source[E, NotUsed]
建立一個Source,它會將S型別的值展開成一對下一個狀態S,'E`型別的輸出元素。
例如,10M以下的所有斐波納契數字:

Source.unfold(0 → 1) {
    case (a, _) if a > 10000000 ⇒ None
    case (a, b) ⇒ Some((b → (a + b)) → a)
 }

(13)unfoldAsync[S, E](s: S)(f: S ⇒ Future[Option[(S, E)]]): Source[E, NotUsed]
與unfold相同,但是使用一個非同步函式來產生下一個狀態元素元組。

Source.unfoldAsync(0 → 1) {
     case (a, _) if a > 10000000 ⇒ Future.successful(None)
     case (a, b) ⇒ Future{
       Thread.sleep(1000)
       Some((b → (a + b)) → a)
     }
 }

(14)empty[T]: Source[T, NotUsed]
建立一個沒有元素的Source,即為每個連線的Sink立即完成的空流。
例如:Source.empty

(15)maybe[T]: Source[T, Promise[Option[T]]]
建立一個Source,它物化為一個scala.concurrent.Promise,它控制什麼元素從Source發出。

如果物化的promise以Some完成,那麼該值將在下游生成,然後是完成。
如果物化的promise以None完成,那麼下游不會產生值,並立即發出完成訊號。
如果物化的promise以failure完成,那麼返回的source將以那個錯誤終止。
如果在promise完成前,source的下游取消,那麼promise將以None完成。

(16)failed[T](cause: Throwable): Source[T, NotUsed]
建立一個Source,它立刻終止流,並將錯誤cause給每一個連線的Sink。
例如:

val ex = new Exception("buh")
Source.failed(ex)
     .flatMapMerge(1, identity)
     .runWith(Sink.head)
      .futureValue

(17)lazily[T, M](create: () ⇒ Source[T, M]): Source[T, Future[M]]
建立一個Source,直到下游有需求才物化,當source物化時,物化的future將以其值完成,如果下游取消或失敗沒有任何需求,則不會呼叫建立工廠,物化的Future是失敗。

(18)asSubscriber[T]: Source[T, Subscriber[T]]
建立一個Source,其物化為一個org.reactivestreams.Subscriber

(19)actorRef[T](bufferSize: Int, overflowStrategy: OverflowStrategy): Source[T, ActorRef]
如何先定義流,而後給流傳遞資料呢?答案就是Source.actorRef。說明:Source.actorRef沒有背壓策略。
建立一個Source,其物化為一個akka.actor.ActorRef

如果下游有需求, 傳送到該actor的訊息將被髮送到流中, 否則它們將被緩衝, 直到收到需求請求為止。

根據定義的akka.stream.OverflowStrategy,如果緩衝區中沒有可用空間, 則可能會丟棄元素。

策略akka.stream.OverflowStrategy.backpressure不受支援, 如果將其作為引數傳遞, 則會丟擲異常 llegalArgument ( "Backpressure overflowStrategy not supported")。

可以使用0的bufferSize禁用緩衝區, 如果下游沒有需求, 則會丟棄接收到的訊息。當 bufferSize是 0, overflowStrategy並不重要。在此源之後新增一個非同步邊界;因此, 假定下游總是會產生需求是絕不會安全的。

通過將akka.actor.Status.Failure傳送到actor引用, 從而失敗來完成流。在標示完成前,以防actor仍消耗其內部緩衝區(在收到一個akka.actor.Status.Success之後),它收到一個akka.actor.Status.Failure,故障將為 立即向下遊發訊號(而不是完成訊號)。

當流完成、失敗或從下游取消時, actor將被停止, 即您可以在發生此情況時觀察它以獲得通知。

val stringSourceinFuture=Source.actorRef[String](100,OverflowStrategy.fail) // 快取最大為100,超出的話,將以失敗告終
  val hahaStrSource=stringSourceinFuture.filter(str=>str.startsWith("haha")) //source資料流中把不是以"haha"開頭的字串過濾掉
  val actor=hahaStrSource.to(Sink.foreach(println)).run()
  actor!"asdsadasd"
  actor!"hahaasd"
  actor!Success("ok")// 資料流成功完成並關閉

(20)combine[T, U](first: Source[T, _], second: Source[T, _], rest: Source[T, _]*)(strategy: Int ⇒ Graph[UniformFanInShape[T, U], NotUsed]): Source[U, NotUsed]
MergeConcat按照扇入策略將多個Source合併,返回一個Source。
例如:

val sourceOne = Source(List(1))
val sourceTwo = Source(List(2))
val merged = Source.combine(sourceOne, sourceTwo)(Merge(_))

val mergedResult: Future[Int] = merged.runWith(Sink.fold(0)(_ + _))

(21)zipN[T](sources: immutable.Seq[Source[T, _]]): Source[immutable.Seq[T], NotUsed]
將多個流的元素合併到一個序列流中。

val sources = immutable.Seq(
        Source(List(1, 2, 3)),
        Source(List(10, 20, 30)),
        Source(List(100, 200, 300)))

Source.zipN(sources)
        .runWith(Sink.seq)
        .futureValue

結果是:

immutable.Seq(
          immutable.Seq(1, 10, 100),
          immutable.Seq(2, 20, 200),
          immutable.Seq(3, 30, 300))

(22)zipWithN[T, O](zipper: immutable.Seq[T] ⇒ O)(sources: immutable.Seq[Source[T, _]]): Source[O, NotUsed]
使用組合函式將多個流的元素合併到一個序列流中。

val sources = immutable.Seq(
        Source(List(1, 2, 3)),
        Source(List(10, 20, 30)),
        Source(List(100, 200, 300)))

Source.zipWithN[Int, Int](_.sum)(sources)
        .runWith(Sink.seq)
        .futureValue

結果是:

immutable.Seq(111, 222, 333)

(23)queue[T](bufferSize: Int, overflowStrategy: OverflowStrategy): Source[T, SourceQueueWithComplete[T]]
建立一個Source,它物化為````akka.stream.scaladsl.SourceQueue```。

您可以將元素推送到佇列中, 如果下游有需求, 則它們將被髮送到流中, 否則它們將被緩衝, 直到收到需求請求為止。如果下游終止, 緩衝區中的元素將被丟棄。

根據定義的akka.stream.OverflowStrategy,如果緩衝區中沒有可用空間, 則可能會丟棄元素。

確認機制可用。
akka.stream.scaladsl.SourceQueue.offer返回Future [QueueOfferResult],如果元素被新增到緩衝區或傳送到下游,則它將以QueueOfferResult.Enqueued完成。 如果元素被丟棄,它將以QueueOfferResult.Dropped完成。當流失敗時,以QueueOfferResult.Failure完成 或者下游完成時,以
QueueOfferResult.QueueClosed完成。

當緩衝區已滿時,策略akka.stream.OverflowStrategy.backpressure不會完成最後offer():Future呼叫。

可以使用akka.stream.scaladsl.SourceQueue.watchCompletion檢視流的可訪問性。當流完成時,它返回一個以成功完成的future或者當流失敗時,它返回一個以失敗完成的future。

可以通過設定bufferSize為0關閉緩衝區,然後接收到的訊息將等待下游的需求,如果有另一個訊息等待下游需求,這種情況下結果將根據溢位策略完成。

(24)unfoldResource[T, S](create: () ⇒ S, read: (S) ⇒ Option[T], close: (S) ⇒ Unit): Source[T, NotUsed]
從某個可以開啟、讀取、關閉的資源,建立一個Source。
以阻塞的方式與資源互動。

可以使用監管策略來處理read函式的異常。所有由createclose丟擲的異常,都將使流失敗。

Restart監管策略將關閉並再次建立阻塞IO。預設策略是Stop,意味著在read函式出現錯誤流將終止。

通過變更akka.stream.blocking-io-dispatcher或者為提供的Source使用ActorAttributes設定,來配置預設的排程器。

遵守ActorAttributes. SupervisionStrategy屬性。

(25)unfoldResourceAsync[T, S](create: () ⇒ Future[S], read: (S) ⇒ Future[Option[T]], close: (S) ⇒ Future[Done]): Source[T, NotUsed]
類似於unfoldResource,但是使用返回Futures而不是純值的函式。

相關文章