Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Design Patterns - Tools of the Trade by Jamie Allen

Riga Dev Day
March 13, 2016
290

Reactive Design Patterns - Tools of the Trade by Jamie Allen

Riga Dev Day

March 13, 2016
Tweet

Transcript

  1. Reactive Design Patterns Implications are massive, change is unavoidable Users

    are demanding richer and more personalized experiences. Yet, at the same time, expecting blazing fast load time. Users Mobile and HTML5; Data and compute clouds; scaling on demand. Modern application technologies are fueling the always-on, real-time user expectation. Applications Businesses are being pushed to react to these changing user expectations… ...and embrace 
 modern application requirements. Businesses
  2. Reactive Design Patterns Cost of Not Being Reactive • Cost

    to your wallet and the environment • No ability to recover from failure • No ability to be responsive to our users
  3. Reactive Design Patterns Functional Programming is Key • We want

    to be asynchronous and non-blocking • We need to ensure that our data is protected without locks • Functional programming is critical to meeting these needs • Declarative • Immutable • Referentially transparent • Pure functions that only have inputs and outputs
  4. Reactive Design Patterns Backpressure is required • How can a

    system withstand variance in load? • What does the system communicate to users of the application when it is overwhelmed? • Companies can lose tremendous amounts of money by not being able to respond to users at all times
  5. Reactive Design Patterns Tools of the Trade All code can

    be found at https://github.com/ReactiveDesignPatterns/Chapter-2
  6. Reactive Design Patterns Tools of the Trade: Event Loops •

    Leverage green threads to provide asynchronous semantics • The core concept of Node.js and Vert.x • Powerful abstraction for performance and potentially scalability • Limited with respect to resilience • One error can take down multiple events • Node.js can only be restarted via init.d or system.d • Need to be able to recapture events lost, if important • Limited with respect to communication • Node processes can fork another process, but can't talk to it without IPC • Callback model leads to tangled code
  7. Reactive Design Patterns Node.js Example var http = require('http'); var

    counter = 0; http.createServer(function (req, res) { counter++; res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Sending response: ' + counter + ' via callback!\n'); }).listen(8888, '127.0.0.1'); console.log('Server up on 127.0.0.1:8888, send requests!');
  8. Reactive Design Patterns Tools of the Trade: CSP • Communicating

    Sequential Processes • Decouples the sender and receiver by leveraging a "channel" • The underlying principle behind Go's Channels and Clojure's core.async • Theoretically able to statically verify a deadlock will occur at compilation time, though no popular implementation does currently does this • No inherent ability to send messages in a distributed environment • No supervision for fault tolerance
  9. Reactive Design Patterns Go Example package main import ( "fmt"

    "time" ) func main() { iterations := 10 myChannel := make(chan int) go producer(myChannel, iterations) go consumer(myChannel, iterations) time.Sleep(500 * time.Millisecond) } func producer(myChannel chan int, iterations int) { for i := 1; i <= iterations; i++ { fmt.Println("Sending: ", i) myChannel <- i } } func consumer(myChannel chan int, iterations int) { for i := 1; i <= iterations; i++ { recVal := <-myChannel fmt.Println("Received: ", recVal) } }
  10. Reactive Design Patterns Futures • Allow you to define behavior

    that will be executed on another thread at some time • Responses can be handled with callbacks or higher-order functions (map, flatMap), and can be composed into complex interactions • Not supervised, but do allow explicit fault tolerance via failure callback definition
  11. Reactive Design Patterns Java8 CompletableFuture Example package org.reactivedesignpatterns.chapter2.future; import java.util.concurrent.CompletableFuture;

    import java.util.function.Supplier; public class ParallelRetrievalExample { final CacheRetriever cacheRetriever; final DBRetriever dbRetriever; ParallelRetrievalExample(CacheRetriever cacheRetriever, DBRetriever dbRetriever) { this.cacheRetriever = cacheRetriever; this.dbRetriever = dbRetriever; } public Object retrieveCustomer(final long id) { final CompletableFuture<Object> cacheFuture = CompletableFuture .supplyAsync(() -> { return cacheRetriever.getCustomer(id); }); final CompletableFuture<Object> dbFuture = CompletableFuture .supplyAsync(() -> { return dbRetriever.getCustomer(id); }); return CompletableFuture.anyOf(cacheFuture, dbFuture); } }
  12. Reactive Design Patterns Tools of the Trade: CPS and Dataflow

    • Take asynchronous operations and compose them into steps of execution, like a pipeline • Application logic looks synchronous and clean, compiled into code that executes asynchronously • Maintains order of execution • Do not scale across machines • Can be supervised (Akka Dataflow), but failure handling can depend on tool you choose • The platform matters • Green threads/processes (aka fibers) mean less context switching
  13. Reactive Design Patterns Tools of the Trade: Reactive Extensions (RX)

    • Combine the Iterator and Observer patterns into the Observable • Excellent mechanism for handling streams of data • Fault tolerance depends on implementation • Reactive Streams (http://www.reactive-streams.org/) • Introduced the requirement for handling backpressure in overwhelmed systems, as well as a test kit to prove compliance. • Consortium includes Lightbend, Pivotal, Netflix, RedHat, Twitter and more • Interoperability is a core abstraction
  14. Reactive Design Patterns RxJava Example package org.reactivedesignpatterns.chapter2.rxjava; import rx.Observable; import

    rx.functions.Action1; public class RxJavaExample { RxJavaExample() { } public void observe(String[] strings) { Observable.from(strings).subscribe((s) -> { System.out.println("Received " + s); }); } } import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class RxJavaExampleTest { final RxJavaExample rxJavaExample = new RxJavaExample(); @Test public void testRxJava() { String[] strings = { "a", "b", "c" }; rxJavaExample.observe(strings); } }
  15. Reactive Design Patterns Tools of the Trade: Actors • Individual

    entities that can only communicate by passing messages • Excellent for isolating mutable state and protecting it without locks • Location transparency • Supervision • Well-suited for creating state machines • Several implementations, most popular are Erlang and Akka • Best suited for the physical boundaries in your application
  16. Reactive Design Patterns Akka Example class MySupervisor extends Actor {

    // Define how to handle failures in a child override def supervisorStrategy = OneForOneStrategy() { case badJson: InvalidJsonException => { saveInvalidJson(badJson) Resume } case _: BadConnection => Escalate case _ => Restart } // Create the child under me val child = context.actorOf(Props[JsonHandlerAndPersister]) // Handle any messages I may receive def receive = { case _ => } }
  17. Reactive Design Patterns Regardless of the tools you choose, find

    ways to build message-driven, elastic and resilient applications that are responsive to your users