2014 akka-streams-tokyo-japanese

115
Konrad 'ktoso' Malawski GeeCON 2014 @ Kraków, PL Konrad `@ktosopl` Malawski Akka Streams Tokyo Scala User Group @ Tokyo 2014

description

Akka Streams (0.7) talk for the Tokyo Scala User Group, hosted by Dwango. Akka streams are an reactive streams implementation which allows for asynchronous back-pressured processing of data in complext pipelines. This talk aims to highlight the details about how reactive streams work as well as some of the ideas behind akka streams.

Transcript of 2014 akka-streams-tokyo-japanese

Page 1: 2014 akka-streams-tokyo-japanese

Konrad 'ktoso' Malawski GeeCON 2014 @ Kraków, PL

Konrad `@ktosopl` Malawski

Akka Streams

Tokyo Scala User Group @ Tokyo 2014

Page 2: 2014 akka-streams-tokyo-japanese

Konrad `@ktosopl` Malawski

hAkker @ 「アッカ」チームのメンバー。

Page 3: 2014 akka-streams-tokyo-japanese

Konrad `@ktosopl` Malawski

typesafe.com geecon.org

Java.pl / KrakowScala.pl sckrk.com / meetup.com/Paper-Cup @ London

GDGKrakow.pl meetup.com/Lambda-Lounge-Krakow

hAkker @

Page 4: 2014 akka-streams-tokyo-japanese

ありがとうございました, Benedict!

For translating the slides!

Page 5: 2014 akka-streams-tokyo-japanese

You?

?

Page 6: 2014 akka-streams-tokyo-japanese

You?

?

z ?

Page 7: 2014 akka-streams-tokyo-japanese

You?

?

z ?

?

Page 8: 2014 akka-streams-tokyo-japanese

You?

?

z ?

?

?

Page 9: 2014 akka-streams-tokyo-japanese

Streams

Page 10: 2014 akka-streams-tokyo-japanese

Streams

Page 11: 2014 akka-streams-tokyo-japanese

Streams“You cannot enter the same river twice” ~ Heraclitus

http://en.wikiquote.org/wiki/Heraclitus

Page 12: 2014 akka-streams-tokyo-japanese

Streamsライルタイムストリーム処理 Real Time Stream Processing

!

パブリッシャーにつけることが遅ければ、データは川のように流れるため、最初の要素を逃がしてしまう可能性がある When you attach “late” to a Publisher, you may miss initial elements – it’s a river of data.

http://en.wikiquote.org/wiki/Heraclitus

Page 13: 2014 akka-streams-tokyo-japanese

Reactive Streams

Page 14: 2014 akka-streams-tokyo-japanese

Reactive Streams

!

!

Stream processing

Page 15: 2014 akka-streams-tokyo-japanese

Reactive Streams

Back-pressured !

Stream processing

Page 16: 2014 akka-streams-tokyo-japanese

Reactive Streams

Back-pressured Asynchronous

Stream processing

Page 17: 2014 akka-streams-tokyo-japanese

Reactive Streams

Back-pressured Asynchronous

Stream processing Standardised (!)

Page 18: 2014 akka-streams-tokyo-japanese

Reactive Streams: Goals

1. Back-pressured Asynchronous Stream processing !

2. Standard implemented by many libraries

Page 19: 2014 akka-streams-tokyo-japanese

Reactive Streams - Specification & TCK

http://reactive-streams.org

Page 20: 2014 akka-streams-tokyo-japanese

Reactive Streams - Who?

http://reactive-streams.org

Kaazing Corp. rxJava @ Netflix,

reactor @ Pivotal (SpringSource), vert.x @ Red Hat,

Twitter, akka-streams @ Typesafe,

spray @ Spray.io, Oracle,

java (?) – Doug Lea - SUNY Oswego …

Page 21: 2014 akka-streams-tokyo-japanese

Reactive Streams - Inter-op

http://reactive-streams.org

システム達を協力させたい. We want to make different implementations

co-operate with each other.

Page 22: 2014 akka-streams-tokyo-japanese

Reactive Streams - Inter-op

http://reactive-streams.org

リアクティブストリームのプロトコールを

使ってシステム達を話し合わせる The different implementations “talk to each other”

using the Reactive Streams protocol.

Page 23: 2014 akka-streams-tokyo-japanese

Reactive Streams - Inter-op

http://reactive-streams.org

リアクティブストリームSPIはユーザーAPIではない。

対象システムのライブラリを使うべき。 The Reactive Streams SPI is NOT meant to be user-api.

You should use one of the implementing libraries.

Page 24: 2014 akka-streams-tokyo-japanese

Back-pressure, なにですか?

Page 25: 2014 akka-streams-tokyo-japanese

Back-pressure? Example Without

Publisher[T] Subscriber[T]

Page 26: 2014 akka-streams-tokyo-japanese

Back-pressure? Example Without

速度が早いパブリッシャー Fast Publisher 速度が遅いサブスクライバー

Slow Subscriber

Page 27: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model

Page 28: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model

Page 29: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model通常の場合、サブスクライバーはバッファーがある.

Subscriber usually has some kind of buffer.

Page 30: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model

Page 31: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model

Page 32: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK modelバッファーが溢れてしまった場合、どうなる? What if the buffer overflows?

Page 33: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model (a)

有界バッファーを利用して、溢れてしまったメッセージを落とし、再送を求める.

!Use bounded buffer, drop messages + require re-sending

Page 34: 2014 akka-streams-tokyo-japanese

有界バッファーを利用して、溢れてしまったメッセージを落とし、再送を求める.

!Use bounded buffer, drop messages + require re-sending

Back-pressure? Push + NACK model (a)

Kernel does this! Routers do this!

(TCP)

Page 35: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model (b)バッファーの容量を増やす・・・まぁ、

メモリ容量がある限り! Increase buffer size… Well, while you have memory available!

Page 36: 2014 akka-streams-tokyo-japanese

Back-pressure? Push + NACK model (b)

Page 37: 2014 akka-streams-tokyo-japanese

Back-pressure? Why NACKing is NOT enough

Page 38: 2014 akka-streams-tokyo-japanese

Back-pressure? Example NACKingたいへんですよ!

バッファーが溢れるまで間もなく! Buffer overflow is imminent!

Page 39: 2014 akka-streams-tokyo-japanese

Back-pressure? Example NACKingデータを送る速力を落とす、または送信を停止する、

ようにパブリッシャーに告げる. Telling the Publisher to slow down / stop sending…

Page 40: 2014 akka-streams-tokyo-japanese

Back-pressure? Example NACKingメッセージが送信されている最中のため、

NACKが間に合わなかった! NACK did not make it in time,

because M was in-flight!

Page 41: 2014 akka-streams-tokyo-japanese

Back-pressure? !

パブリッシャーの速度 < サブスクライバーの速度 speed(publisher) < speed(subscriber)

Page 42: 2014 akka-streams-tokyo-japanese

Back-pressure? Fast Subscriber, No Problem

速度が速いサブスクライバーなら、問題ない!No problem!

Page 43: 2014 akka-streams-tokyo-japanese

Back-pressure? Reactive-Streams

= “Dynamic Push/Pull”

Page 44: 2014 akka-streams-tokyo-japanese

プッシュ一方 - 速度が遅いサブスクライバーの場合、 安全じゃない

Just push – not safe when Slow Subscriber !!

プル一方 - 速度早いサブスクライバーの場合、 遅すぎる

Just pull – too slow when Fast Subscriber

Back-pressure? RS: Dynamic Push/Pull

Page 45: 2014 akka-streams-tokyo-japanese

プッシュ一方 - 速度が遅いサブスクライバーの場合、 安全じゃない

Just push – not safe when Slow Subscriber !!

プル一方 - 速度早いサブスクライバーの場合、 遅すぎる

Just pull – too slow when Fast Subscriber !

Solution: 動的な調整(リアクティブストリーム)

Dynamic adjustment (Reactive Streams)

Back-pressure? RS: Dynamic Push/Pull

Page 46: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pull速度が遅いサブスクライバーは自分のバッファーが3つの要素まで受け取られる。パブリッシャーはサブスクライバーのバッファーが溢れるほどデータを送らない。Slow Subscriber sees it’s buffer can

take 3 elements. Publisher will never blow up it’s buffer.

Page 47: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pull速度が速いパブリッシャーは最大でも3つの要素を送る。これは、プル型のback-pressure. Fast Publisher will send at-most 3 elements. This is pull-based-backpressure.

Page 48: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pull

速度が速いサブスクライバーは、実際のデータが届く前に、たくさんリクエストを送ることができる!Fast Subscriber can issue more Request(n), before more data arrives!

Page 49: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pullパブリッシャーはサブスクライバーの全てのリクエストを溜める. Fast Subscriber can issue more Request(n), before more data arrives. Publisher can accumulate demand.

Page 50: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Accumulate demand

パブリッシャーはサブスクライバーの全ての

リクエストを溜める. Publisher accumulates total demand per subscriber.

Page 51: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Accumulate demand溜まった要素をパブリッシュすることは安全だ。サブスクライバーのバッファーは溢れない。 Total demand of elements is safe to publish. Subscriber’s buffer will not overflow.

Page 52: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Requesting “a lot”速度が速いサブスクライバーは、パブリッシャーに対し要求が多くても良い。これは「パブリッシャー・プッシュ」だ。バッファー容量は知られているので、安全だ。

Page 53: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Requesting “a lot”

Fast Subscriber, can request “a lot” from Publisher. This is effectively “publisher push”, and is really fast. Buffer size is known and this is safe.

Page 54: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pull

MAX速度

Page 55: 2014 akka-streams-tokyo-japanese

Back-pressure? RS: Dynamic Push/Pull

安全!溢れること絶対ない!

MAX速度

Page 56: 2014 akka-streams-tokyo-japanese

わなにですか?

Page 57: 2014 akka-streams-tokyo-japanese

Akka = アッカAkka is a high-performance concurrency library for Scala and Java. !

At it’s core it focuses on the Actor Model:

Page 58: 2014 akka-streams-tokyo-japanese

アクターができること:

• メッセージを送信・受信する (Send / receive messages)

• アクターを作る (Create Actors)

• 自分の動作を変える (Change it’s behaviour)

Akka = アッカAkka is a high-performance concurrency library for Scala and Java. !

At it’s core it focuses on the Actor Model:

Page 59: 2014 akka-streams-tokyo-japanese

AkkaAkka has multiple modules: !

Akka-camel: integration Akka-remote: remote actors Akka-cluster: clustering Akka-persistence: CQRS / Event Sourcing Akka-streams: stream processing …

Page 60: 2014 akka-streams-tokyo-japanese

Akka Streams 0.7 early preview

Page 61: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

Page 62: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

Page 63: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

Page 64: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

Page 65: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

FlowFrom[Double].map(_.toInt). [...]

ソースはまだ付けられていない.

パイプはダブルを処理する準備を整いた. No Source attached yet.

“Pipe ready to work with Doubles”.

Page 66: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!!

アクターが住んでいる世界.

AkkaStreamsはアクターを使うため、

アクターシステムは必要.

!ActorSystem is the world in which Actors live in.

AkkaStreams uses Actors, so it needs ActorSystem.

Page 67: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!implicit val mat = FlowMaterializer()!

ストリームをどうやって具体化するかの

ロジックが含まれている.

!Contains logic on HOW to materialise the stream.

Page 68: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!implicit val mat = FlowMaterializer()!

単純にアクターか、もしくは実装されていれば、

Apache Spark (?!) !

A materialiser can choose HOW to materialise, it could even use Apache Spark (?!) if someone would implement that… :-)

Page 69: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!implicit val mat = FlowMaterializer()!

バッファーの容量を設定できるなど !

You can configure it’s buffer sizes etc.

Page 70: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!implicit val mat = FlowMaterializer()!

val foreachSink = ForeachSink[Int](println)!val mf = FlowFrom(1 to 3).withSink(foreachSink).run()

Uses the implicit FlowMaterializer

Page 71: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

implicit val sys = ActorSystem("tokyo-sys")!implicit val mat = FlowMaterializer()!

val foreachSink = ForeachSink[Int](println)!val mf = FlowFrom(1 to 3).withSink(foreachSink).run()(mat)

Page 72: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val mf = FlowFrom[Int].! map(_ * 2).! withSink(ForeachSink(println)) // needs source,! // can NOT run

走らせるためにソースが必要!

Page 73: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val f = FlowFrom[Int].! map(_ * 2).!! ! ! withSink(ForeachSink(i => println(s"i = $i”))).! ! ! // needs Source to run!

インプットが必要

走らせるためにソースが必要!

Page 74: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val f = FlowFrom[Int].! map(_ * 2).!! ! ! withSink(ForeachSink(i => println(s"i = $i”))).! ! ! // needs Source to run!

Page 75: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val f = FlowFrom[Int].! map(_ * 2).!! ! ! withSink(ForeachSink(i => println(s"i = $i”))).! ! ! // needs Source to run!

Page 76: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val f = FlowFrom[Int].! map(_ * 2).!! ! ! withSink(ForeachSink(i => println(s"i = $i”))).! ! ! // needs Source to run!

!! ! ! f.withSource(IterableSource(1 to 10)).run()

準備完了!

Page 77: 2014 akka-streams-tokyo-japanese

Akka Streams – Linear Flow

val f = FlowFrom[Int].! map(_ * 2).!! ! ! withSink(ForeachSink(i => println(s"i = $i”))).! ! ! // needs Source to run!

!! ! ! f.withSource(IterableSource(1 to 10)).run()

準備完了!

Page 78: 2014 akka-streams-tokyo-japanese

Akka Streams – Flows are reusable

!! ! ! f.withSource(IterableSource(1 to 10)).run()! ! ! ! f.withSource(IterableSource(1 to 100)).run()! ! ! ! f.withSource(IterableSource(1 to 1000)).run()

Page 79: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

val subscriber = system.actorOf(Props[SubStreamParent], ”parent")!!FlowFrom(1 to 100).! map(_.toString).! filter(_.length == 2).! drop(2).! groupBy(_.last).! publishTo(ActorSubscriber(subscriber))!

Page 80: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

val subscriber = system.actorOf(Props[SubStreamParent], ”parent")!!FlowFrom(1 to 100).! map(_.toString).! filter(_.length == 2).! drop(2).! groupBy(_.last).! publishTo(ActorSubscriber(subscriber))!

各グループもストリームだよ! Each “group” is a stream too! It’s a “Stream of Streams”.

Page 81: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced! groupBy(_.last).

「11」をグループ「1」に、「12」をグループ「2」になど GroupBy groups “11” to group “1”, “12” to group “2” etc.

Page 82: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced! groupBy(_.last).

サブスクライバーに[グループキー、サブストリームフロー]を提供する

It offers (groupKey, subStreamFlow) to Subscriber

Page 83: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced! groupBy(_.last).

子供を起動させ、サブーフローを扱わせる It can then start children, to handle the sub-flows!

Page 84: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced! groupBy(_.last).

例えば、グループ毎に1人の子供 For example, one child for each group.

Page 85: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

val subscriber = system.actorOf(Props[SubStreamParent], ”parent")!!FlowFrom(1 to 100).! map(_.toString).! filter(_.length == 2).! drop(2).! groupBy(_.last).! publishTo(ActorSubscriber(subscriber))!

普通 Akka Actor, will consume SubStream offers.

Page 86: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber ! with ImplicitFlowMaterializer ! with ActorLogging {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext((groupId: String, subStream: FlowWithSource[_, _])) =>!! val subSub = context.actorOf(Props[SubStreamSubscriber], ! s"sub-$groupId")! subStream.publishTo(ActorSubscriber(subSub))! }!}!

Page 87: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber ! with ImplicitFlowMaterializer ! with ActorLogging {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext((groupId: String, subStream: FlowWithSource[_, _])) =>!! val subSub = context.actorOf(Props[SubStreamSubscriber], ! s"sub-$groupId")! subStream.publishTo(ActorSubscriber(subSub))! }!}!

Page 88: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber ! with ImplicitFlowMaterializer ! with ActorLogging {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext((groupId: String, subStream: FlowWithSource[_, _])) =>!! val subSub = context.actorOf(Props[SubStreamSubscriber], ! s"sub-$groupId")! subStream.publishTo(ActorSubscriber(subSub))! }!}!

Page 89: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber ! with ImplicitFlowMaterializer ! with ActorLogging {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext((groupId: String, subStream: FlowWithSource[_, _])) =>!! val subSub = context.actorOf(Props[SubStreamSubscriber], ! s"sub-$groupId")! subStream.publishTo(ActorSubscriber(subSub))! }!}!

Page 90: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber ! with ImplicitFlowMaterializer ! with ActorLogging {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext((groupId: String, subStream: FlowWithSource[_, _])) =>!! val subSub = context.actorOf(Props[SubStreamSubscriber], ! s"sub-$groupId")! subStream.publishTo(ActorSubscriber(subSub))! }!}!

Page 91: 2014 akka-streams-tokyo-japanese

Akka Streams <-> Actors – Advanced

class SubStreamParent extends ActorSubscriber {!! override def requestStrategy = OneByOneRequestStrategy!! override def receive = {! case OnNext(n: String) => println(s”n = $n”) ! }!}!

Page 92: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

GraphFlow

Page 93: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

Linear Flows or

non-akka pipelines

Could be another RS implementation!

Page 94: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

Fan-out elements and

Fan-in elements

Page 95: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

Fan-out elements and

Fan-in elements

Now you need a FlowGraph

Page 96: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

// first define some pipeline pieces!val f1 = FlowFrom[Input].map(_.toIntermediate)!val f2 = FlowFrom[Intermediate].map(_.enrich)!val f3 = FlowFrom[Enriched].filter(_.isImportant)!val f4 = FlowFrom[Intermediate].mapFuture(_.enrichAsync)!!// then add input and output placeholders!val in = SubscriberSource[Input]!val out = PublisherSink[Enriched]!

Page 97: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

Page 98: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlowval b3 = Broadcast[Int]("b3")!val b7 = Broadcast[Int]("b7")!val b11 = Broadcast[Int]("b11")!val m8 = Merge[Int]("m8")!val m9 = Merge[Int]("m9")!val m10 = Merge[Int]("m10")!val m11 = Merge[Int]("m11")!val in3 = IterableSource(List(3))!val in5 = IterableSource(List(5))!val in7 = IterableSource(List(7))!

Page 99: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

Page 100: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

// First layer!in7 ~> b7!b7 ~> m11!b7 ~> m8!!in5 ~> m11!!in3 ~> b3!b3 ~> m8!b3 ~> m10!

Page 101: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

!// Second layer!m11 ~> b11!b11 ~> FlowFrom[Int].grouped(1000) ~> resultFuture2 !b11 ~> m9!b11 ~> m10!!m8 ~> m9!

Page 102: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

!// Third layer!m9 ~> FlowFrom[Int].grouped(1000) ~> resultFuture9!m10 ~> FlowFrom[Int].grouped(1000) ~> resultFuture10!

Page 103: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

!// Third layer!m9 ~> FlowFrom[Int].grouped(1000) ~> resultFuture9!m10 ~> FlowFrom[Int].grouped(1000) ~> resultFuture10!

Page 104: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

!// Third layer!m9 ~> FlowFrom[Int].grouped(1000) ~> resultFuture9!m10 ~> FlowFrom[Int].grouped(1000) ~> resultFuture10!

Page 105: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

val resultFuture2 = FutureSink[Seq[Int]]!val resultFuture9 = FutureSink[Seq[Int]]!val resultFuture10 = FutureSink[Seq[Int]]!!val g = FlowGraph { implicit b =>! // ...! m10 ~> FlowFrom[Int].grouped(1000) ~> resultFuture10! // ...!}.run()!!Await.result(g.getSinkFor(resultFuture2), 3.seconds).sorted! should be(List(5, 7))

Sinks and Sources are “keys” which can be addressed within the graph

Page 106: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

val resultFuture2 = FutureSink[Seq[Int]]!val resultFuture9 = FutureSink[Seq[Int]]!val resultFuture10 = FutureSink[Seq[Int]]!!val g = FlowGraph { implicit b =>! // ...! m10 ~> FlowFrom[Int].grouped(1000) ~> resultFuture10! // ...!}.run()!!Await.result(g.getSinkFor(resultFuture2), 3.seconds).sorted! should be(List(5, 7))

Sinks and Sources are “keys” which can be addressed within the graph

Page 107: 2014 akka-streams-tokyo-japanese

Akka Streams – GraphFlow

!val g = FlowGraph {}!

FlowGraphは不変で、安全に共有でき、

何度も使いまわせる!

!FlowGraph is immutable and safe to share and re-use! Think of it as “the description” which then gets “run”.

Page 108: 2014 akka-streams-tokyo-japanese

Available Elements 0.7 early preview

Page 109: 2014 akka-streams-tokyo-japanese

Available Sources• FutureSource • IterableSource • IteratorSource • PublisherSource • SubscriberSource • ThunkSource • TickSource (timer based) • 簡単に自分のものを追加できる!

… easy to add your own!

0.7 early preview

Page 110: 2014 akka-streams-tokyo-japanese

Available operations• buffer • collect • concat • conflate • drop / dropWithin • take / takeWithin • filter • fold • foreach • groupBy • grouped • map • onComplete • prefixAndTail

• broadcast • merge / “generalised merge” • zip • 自分のオペレーションを追加する事は可能!

… possible to add your own!

0.7 early preview

Page 111: 2014 akka-streams-tokyo-japanese

Available Sinks• BlackHoleSink • FoldSink • ForeachSink • FutureSink • OnCompleteSink • PublisherSink / FanoutPublisherSink • SubscriberSink • 簡単に自分のものを追加できる!

… easy to add your own!

0.7 early preview

Page 112: 2014 akka-streams-tokyo-japanese

Spray => Akka-Http && ReactiveStreams

Spray is now merged into Akka, as Akka-Http Works on Reactive Streams

Streaming end-to-end!

Page 113: 2014 akka-streams-tokyo-japanese

Links• http://akka.io • http://reactive-streams.org • https://groups.google.com/group/akka-user <- ask questions here! • http://akka.io/news/2014/09/12/akka-streams-0.7-released.html

Page 114: 2014 akka-streams-tokyo-japanese

ありがとう ございました! Ask questions, get Stickers!

http://akka.io

ktoso @ typesafe.com twitter: ktosopl github: ktoso team blog: letitcrash.com

Page 115: 2014 akka-streams-tokyo-japanese

©Typesafe 2014 – All Rights Reserved