eynkywtka-reactive-streams



eynkywtka-reactive-streams

0 1


eynkywtka-reactive-streams

Everything you never knew you wanted to know about Reactive Streams

On Github bjartek / eynkywtka-reactive-streams

Everything you never knew you wanted to know about

Reactive Streams

Bjarte Stien Karlsen @ SITS

slides created with revealit/reveal.js

Agenda

  • Why go Reactive?
  • The Reactive Manifesto
  • Streams
  • Reactive Streams
  • Implementations
  • Books
  • Thanks

Why go Reactive?

Kilde: The free lunch is over - Herb Sutter
Parallelisation is key!

Our old tools don't cut it

  • Threads (programmed directly)
    • high memory overhead
    • starting/stopping is expensive
    • inter-thread communication entirely left to the user
  • Locks/Mutexes/Semaphores/`synchronized`/`volatile`
    • too little sync: race conditions, wrong results
    • too much sync: deadlocks, poor performance
    • very hard to use correctly

Too low-level!

Selected concurrency abstractions

Reactive Manifesto

Kilde: Reactive Manifesto

Responsive

  • responds in a timemly manner if at all possible
  • focus on providing rapid and consistent response times
  • establishing reliable upper bounds
  • deliver a consistent quality of service.
  • simplifies error handling,

Resilient

  • Let it crash
  • stays responsive in the face of failure
  • achieved by replication, containment, isolation and delegation
  • failures are contained within each component
  • recovery of each component is delegated to another (external) component

Elastic

  • stays responsive under varying workload
  • scale resources based on input rate
  • implies designs that have no contention points or central bottlenecks

Message Driven

  • asynchronous message-passing to establish a boundary between components
  • ensures loose coupling, isolation, location transparency
  • delegate errors as messages
  • enables load management, elasticity, and flow control
  • shaping and monitoring the message queues in the system and applying back-pressure

Streams

Kilde: birkenes-avisa.no
Kilde: http://www.cgenarchive.org/uploads/2/5/2/6/25269392/7797686_orig.jpg

Common Uses of Streams

  • Bulk data transfer
  • Real-time data sources
  • Batch processing of large data sets
  • Monitoring and analytics
  • Structuring and Scaling Business Logic

Example: Scaling Logic

A stream is not an colleciton

  • size
  • x.head + x.tail
  • iterate all elements
  • content not dependent on who is processing
  • content not dependent on when it is processed
  • speed of the processor
  • speed of the producer

Why not java 8 stream

Simple stream example

import java.util.stream.*

final Stream<Integer> s = Stream.of(1,2,3);

final Stream<String> s2 = s.map(i -> "a" + 1);

s2.iterator(); //pull

s2.forEach(i -> System.out.println(i));  //push

Java8 Stream

  • dsl for describing transformation
  • staged computation
  • cannot be reused
  • eager model of execution
  • push/pull chosen statically

Reactive Streams

statically-typed, high-performance, low latency, asynchronous streams of data with built-in non-blocking back pressure

Success formula

  • minimial interface
  • rigorous specification of semantics
  • TCK for verification
  • API freedom

Interface

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}
public interface Subscriber<T> {
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}
public interface Subscription {
    public void request(long n);
    public void cancel();
}
public interface Processor<T, R>
        extends Subscriber<T>, Publisher<R> {
}

Not for user consumption! (Use RS Impl Library instead)

sequenceDiagram participant Publisher participant Subscriber Subscriber->>Publisher: subscribe(Subscription) Publisher->>Subscriber: onSubscribe(Subscription) Subscriber->>Publisher: Subscription.request(3) loop 3 times Publisher->>Subscriber: onNext end Publisher->>Subscriber: onComplete | onError

rigorous specification

Backpressure

Async Boundary

Async Boundary

  • Data elements flow downstream
  • Demand flows upstream
  • Data items flow only when there is demand
  • Recipient is in control of incoming data rate
  • Data in flight is bounded by signaled demand
Kilde:http://media-cdn.tripadvisor.com/media/photo-s/05/be/70/1a/river-split.jpg
Kilde: https://hippiefreak69.files.wordpress.com/2015/07/river.jpg

DYNAMIC PUSH/PULL

  • “Push” behavior when consumer is faster
  • “Pull” behavior when producer is faster
  • Switches automatically between these
  • Batching demand allows batching data

ASYNC BOUNDARIES ARE EVERYWHERE

  • Between actors
  • Between threads
  • Between CPUs
  • Between network nodes
  • Between applications

Pipeline Processing Done Right

Continuous Pipelines across Machines

Implementations

Landscape

akka-streams

AKKA-STREAM: BASIC CONCEPTS

  • Built from scratch on Reactive Streams Protocol
  • Java and Scala user APIs
  • Supports fully general stream-graphs
  • Source[T]: the open end of a pipeline producing Ts
  • Sink[T]: an "end-piece" for taking in Ts
  • Flow[A, B]: an unconnected piece of pipeline
  • Generally, all abstractions are re-useable
  • Number of pre-defined transformations still somewhat small
  • Not very optimized yet, still marked "experimental"

AKKA-STREAM: SIMPLE STREAM EXAMPLE

Source(stockTickerPublisher)                 // Source[Tick]
        .filter(_.symbol == "AAPL")                // Source[Tick]
        .buffer(100000, OverflowStrategy.DropHead) // Source[Tick]
        .splitWhen(x => isNewDay(x.timeStamp))     // Source[Source[Tick]]
        .headAndTail                               // Source[(Tick, Source[Tick])]
        .map { case (head, tail) =>
            head -> tail.groupedWithin(1000, 1.second)
        }                                          // Source[(Tick, Source[Seq[[Tick]]])]
        .via(someFlow)                             // Source[RichTick]
        .map(toCandleStickChartColumn)             // Source[CandleStickChartColumn]
        .to(candleStickChartSink)                  // RunnableFlow
        .run()                                     // MaterializedMap

AKKA-STREAM: FLOW GRAPH EXAMPLE

FlowGraph { implicit b ⇒
  val bcast = Broadcast[T]
  val merge = Merge[T]

  source ~> f1 ~> bcast ~> f2 ~> merge ~> f3 ~> sink
                  bcast ~> f4 ~> merge
}.run()

REACTIVE EXTENSIONS

  • Mostly driven by Netflix Engineers
  • Broke the ground for Reactive Streams
  • Oldest, most known, most mature
  • Support for many different languages
  • Doesn't directly support RS yet,
  • currently still needs adapter lib
  • Backpressure not fully supported yet,
  • will do so in version 2.0

REACTOR

  • RS implementation built from scratch
  • Java only
  • Internally based a lot on Disruptor
  • Focus: Performance
  • Current version (2.0.3) not very mature yet
  • Driven by Engineers from Pivotal

Examples

Books

Sources

Mathias Doenitz presentation for Berlin Scala User group Roland Kuhns webinar about reactive streams Mathias Doenitz presentation for scala days 2015

Reactive streams will be in java9!

Everything you never knew you wanted to know about Reactive Streams Bjarte Stien Karlsen @ SITS slides created with revealit/reveal.js