Slide 1

Slide 1 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. Scala in the City - July 2018

Slide 2

Slide 2 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. MONITORING (AKKA) STREAMS

Slide 3

Slide 3 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. Stefano Bonetti Software Engineer @svezfaz @svez_faz

Slide 4

Slide 4 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. FIRST-TO-KNOW 4

Slide 5

Slide 5 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT BACKPRESSURE

Slide 6

Slide 6 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT BACKPRESSURE

Slide 7

Slide 7 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT (/s) 7 Web Service req res

Slide 8

Slide 8 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 8 CHALLENGE 1 - TOPOLOGY

Slide 9

Slide 9 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 9 CHALLENGE 1 - TOPOLOGY © Kevin Cappis 2004

Slide 10

Slide 10 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. CHALLENGE 2 - LOWER I/O CORRELATION 10 web service

Slide 11

Slide 11 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. CHALLENGE 2 - LOWER I/O CORRELATION 11 Processor[T, S]

Slide 12

Slide 12 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 12 © Kevin Cappis 2004

Slide 13

Slide 13 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. TRANSPARENT PROCESSORS 13 Processor[T, S] Processor[T, S] Publisher[T] Subscriber[S]

Slide 14

Slide 14 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. TRANSPARENT PROCESSORS 14 Processor[T, S] Processor[T, S] Publisher[T] Subscriber[S] c1 c2 c3 c4 Processor[T, T] Processor[S, S]

Slide 15

Slide 15 text

val pangram = Source(List("The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")) val toChars = Flow[String].mapConcat(_.toList) val print = Sink.foreach(println) pangram .via(toChars) .runWith(print) AKKA STREAMS - THROUGHPUT

Slide 16

Slide 16 text

val pangram = Source(List("The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")) val toChars = Flow[String].mapConcat(_.toList) val print = Sink.foreach(println) pangram .via(toChars) .runWith(print) AKKA STREAMS - THROUGHPUT

Slide 17

Slide 17 text

val pangram = Source(List("The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")) val toChars = Flow[String].mapConcat(_.toList) val print = Sink.foreach(println) def meter[T](name: String): Flow[T, T, NotUsed] = { val msgCounter = Kamon.metrics.counter(name) Flow[T].map { x ⇒ msgCounter.increment(); x } } pangram .via(meter("produced")) .via(toChars) .via(meter("processed")) .runWith(print) AKKA STREAMS - THROUGHPUT

Slide 18

Slide 18 text

val pangram = Source(List("The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")) val toChars = Flow[String].mapConcat(_.toList) val print = Sink.foreach(println) def meter[T](name: String): Flow[T, T, NotUsed] = { val msgCounter = Kamon.metrics.counter(name) Flow[T].map { x ⇒ msgCounter.increment(); x } } pangram .via(meter("produced")) .via(toChars) .via(meter("processed")) .runWith(print) AKKA STREAMS - THROUGHPUT

Slide 19

Slide 19 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT BACKPRESSURE

Slide 20

Slide 20 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT BACKPRESSURE

Slide 21

Slide 21 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. EXAMPLE 21 Validation/ Filtering Commit Kafka offset valid invalid Store via API

Slide 22

Slide 22 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. Store via API EXAMPLE 22 Validation/ Filtering Commit Kafka offset valid invalid 100/s 75/s 25/s 75/s

Slide 23

Slide 23 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. Store via API EXAMPLE 23 Validation/ Filtering Commit Kafka offset valid invalid 100/s 75/s 25/s 75/s 20000/s lag

Slide 24

Slide 24 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 24

Slide 25

Slide 25 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. REACTIVE STREAMS 101 25 Processor Publisher Subscriber request request emit emit

Slide 26

Slide 26 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. REACTIVE STREAMS 101 26 Processor Publisher Subscriber request request emit emit

Slide 27

Slide 27 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. REACTIVE STREAMS 101 27 Processor Publisher Subscriber request request emit emit

Slide 28

Slide 28 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. REACTIVE STREAMS 101 28 Processor Publisher Subscriber request request emit emit

Slide 29

Slide 29 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. REACTIVE STREAMS 101 29 Processor Publisher Subscriber request request emit emit

Slide 30

Slide 30 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. BACKPRESSURE 30 Processor Publisher Subscriber request ? request ? emit emit

Slide 31

Slide 31 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. NO BACKPRESSURE 31 Processor Publisher Subscriber request emit ? emit ? request

Slide 32

Slide 32 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. BACKPRESSURE 32 request emit request request emit Processor Publisher Subscriber request request emit emit

Slide 33

Slide 33 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 33 AKKA STREAMS - GRAPHSTAGE API

Slide 34

Slide 34 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 35

Slide 35 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 36

Slide 36 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 37

Slide 37 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 38

Slide 38 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 39

Slide 39 text

final case class Map[In, Out](f: In ⇒ Out) extends GraphStage[FlowShape[In, Out]] { val in = Inlet[In]("Map.in") val out = Outlet[Out]("Map.out") override val shape = FlowShape(in, out) override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { override def onPush(): Unit = push(out, f(grab(in))) override def onPull(): Unit = pull(in) setHandlers(in, out, this) } } AKKA STREAMS - GRAPHSTAGE API

Slide 40

Slide 40 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 40 AKKA STREAMS - GRAPHSTAGE onPull onPush onPull onPull onPush

Slide 41

Slide 41 text

var lastPulled: Long = System.nanoTime() var lastPushed: Long = lastPulled private val backpressure = Kamon.histogram(label + "_backpressure") override def onPush(): Unit = { push(out, grab(in)) val now = System.nanoTime() backpressure.record((lastPulled - lastPushed) * 100 / now - lastPushed) lastPushed = now } override def onPull(): Unit = { pull(in) lastPulled = System.nanoTime() } setHandlers(in, out, this) AKKA STREAMS - BACKPRESSURE

Slide 42

Slide 42 text

var lastPulled: Long = System.nanoTime() var lastPushed: Long = lastPulled private val backpressure = Kamon.histogram(label + "_backpressure") override def onPush(): Unit = { push(out, grab(in)) val now = System.nanoTime() backpressure.record((lastPulled - lastPushed) * 100 / now - lastPushed) lastPushed = now } override def onPull(): Unit = { pull(in) lastPulled = System.nanoTime() } setHandlers(in, out, this) AKKA STREAMS - BACKPRESSURE

Slide 43

Slide 43 text

var lastPulled: Long = System.nanoTime() var lastPushed: Long = lastPulled private val backpressure = Kamon.histogram(label + "_backpressure") override def onPush(): Unit = { push(out, grab(in)) val now = System.nanoTime() backpressure.record((lastPulled - lastPushed) * 100 / now - lastPushed) lastPushed = now } override def onPull(): Unit = { pull(in) lastPulled = System.nanoTime() } setHandlers(in, out, this) AKKA STREAMS - BACKPRESSURE

Slide 44

Slide 44 text

var lastPulled: Long = System.nanoTime() var lastPushed: Long = lastPulled private val backpressure = Kamon.histogram(label + "_backpressure") override def onPush(): Unit = { push(out, grab(in)) val now = System.nanoTime() backpressure.record((lastPulled - lastPushed) * 100 / now - lastPushed) lastPushed = now } override def onPull(): Unit = { pull(in) lastPulled = System.nanoTime() } setHandlers(in, out, this) AKKA STREAMS - BACKPRESSURE

Slide 45

Slide 45 text

val pangram = Source(List("The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog")) val toChars = Flow[String].mapConcat(_.toList) val print = Sink.foreach(println) pangram .via(backpressureMeter("produced")) .via(toChars) .via(backpressureMeter("processed")) .runWith(print) AKKA STREAMS - BACKPRESSURE

Slide 46

Slide 46 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. THROUGHPUT BACKPRESSURE

Slide 47

Slide 47 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 47 svezfaz/akka-stream-checkpoint CURRENT FEATURES ・ throughput ・ backpressure ratio ・ push-pull latency ・ liveness checks FUTURE WORK ・ failures/completion

Slide 48

Slide 48 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. 48

Slide 49

Slide 49 text

© 2018 HOMEAWAY. ALL RIGHTS RESERVED. Stefano Bonetti Software Engineer @svezfaz @svez_faz Thank you.