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

Why Being Reactive is Good

Why Being Reactive is Good

One of the more difficult aspects of systems architecture is finding concrete terms to describe desirable characteristics that everyone understands. Reactive was one of those terms until two years ago, when the Reactive Manifesto was released. Today, over 12,000 people have signed the online document and participated in its evolution. But what does it mean, and how do the principles described by it help developers engineer systems that are elastic, resilient and responsive to users in the face of bursty load and random/unknown failures? We will discuss these topics, as well as clearly discuss the concepts of asynchronous tasks, non-blocking threads, concurrency issues and parallelism.

The goal of this talk is to frame the term reactive in a positive light, because when it comes to building real-time systems, being reactive is good.

Kevin Webber

October 22, 2015
Tweet

More Decks by Kevin Webber

Other Decks in Programming

Transcript

  1. Problem? » we used the right tools to build the

    wrong thing » proactive isn't always good
  2. Problem? » we used the right tools to build the

    wrong thing » proactive isn't always good » reactive isn't always bad
  3. » let principles guide our » design » tool selection

    » implementation choices » principles should be accessible and universal
  4. » let principles guide our » design » tool selection

    » implementation choices » principles should be accessible and universal » principles should help engineers » meet expectations » take advantage of the latest advancements in technology
  5. asynchronous, non-blocking, real-time, highly- available, loosely coupled, scalable, fault-tolerant, concurrent,

    reactive, event-driven, push instead of pull, distributed, low latency, high throughput...
  6. asynchronous, non-blocking, real-time, highly- available, loosely coupled, scalable, fault-tolerant, concurrent,

    reactive, event-driven, push instead of pull, distributed, low latency, high throughput... Too complicated. We need a simple vocabulary.
  7. Typesafe Reactive Platform » Play: RESTful API framework » Akka:

    Distributed computing framework » Spark: General purpose in- memory compute engine
  8. object GameEngineActor { def props = Props(new GameEngineActor) } class

    GameEngineActor extends Actor { val log = Logging(context.system, this) var openGameQ = new Queue[ActorRef] }
  9. object GameEngineActor { def props = Props(new GameEngineActor) } class

    GameEngineActor extends Actor { val log = Logging(context.system, this) var openGameQ = new Queue[ActorRef] def receive = { // find open game and register player for the game case r: RegisterPlayerRequest => findGame(r) ! r case _ => log.error(_) } }
  10. object GameEngineActor { def props = Props(new GameEngineActor) } class

    GameEngineActor extends Actor { val log = Logging(context.system, this) var openGameQ = new Queue[ActorRef] def receive = { // find open game and register player for the game case r: RegisterPlayerRequest => findGame(r) ! r case _ => log.error(_) } private def findGame(r: RegisterPlayerRequest): ActorRef = { if (openGameQ.isEmpty) { // create a new game and add it to the queue val newGame = { val gameUuid = java.util.UUID.randomUUID.toString context.actorOf(Props[GameActor], name = "gameActor" + gameUuid) } openGameQ += newGame newGame } else { // pull a game off the queue that is waiting for players openGameQ.dequeue } } }
  11. Elastic » scale up » async » non-blocking » scale

    out » immutable data » share nothing
  12. Responsive » responsive to events » responsive to load »

    responsive to failure » responsive to users
  13. » responsive a request for service is always answered, even

    when failures occur. » elastic services scale up and down on demand. » resilient services recover from failures. » message driven services respond to the world, not attempt to control what it does.
  14. How can we envision Proactive Security Solutions as Reactive Security

    Solutions? Using: » Reactive principles » The Typesafe Reactive Platform
  15. How do we get there? Applying the Reactive principles to

    build a fully reactive microservices system, using: » The Typesafe Reactive Platform » Third-party tools » Existing infrastructure (hybrid-cloud, etc)
  16. Play Anatomy » Stateless: session is stored in the browser

    cookie » Actions: user-defined functions that run in a different context than the request loop
  17. Play at its core » RESTful API framework » Familiar

    MVC paradigm » Embraces flows of data » WebSockets, SSE » File uploads
  18. Play at its core » RESTful API framework » Familiar

    MVC paradigm » Embraces flows of data » WebSockets, SSE » File uploads » Integration with Akka » Distribute work via messaging
  19. Single thread per request » A thread keeps data in

    memory until it has access to the CPU
  20. Single thread per request » A thread keeps data in

    memory until it has access to the CPU » More threads = more memory required
  21. Single thread per request » A thread keeps data in

    memory until it has access to the CPU » More threads = more memory required » If a thread is idle while blocked (e.g, IO) » Memory is being consumed inefficiently » Must limit total number of threads » This can leave the CPU idle (bounded on memory)
  22. » Play uses a fork join execution context with work

    stealing » Does not bind a thread to a request
  23. » Play uses a fork join execution context with work

    stealing » Does not bind a thread to a request » Uses Futures and Thread Pools to let CPU go at full throttle
  24. » Play uses a fork join execution context with work

    stealing » Does not bind a thread to a request » Uses Futures and Thread Pools to let CPU go at full throttle » Uses NIO.2 through Netty to avoid blocking on network IO
  25. » Play uses a fork join execution context with work

    stealing » Does not bind a thread to a request » Uses Futures and Thread Pools to let CPU go at full throttle » Uses NIO.2 through Netty to avoid blocking on network IO » Stateless (no HTTP session)
  26. » Play uses a fork join execution context with work

    stealing » Does not bind a thread to a request » Uses Futures and Thread Pools to let CPU go at full throttle » Uses NIO.2 through Netty to avoid blocking on network IO » Stateless (no HTTP session) » No ThreadLocal anywhere
  27. Future[Result] » The async block indicates that the controller will

    return a Future[Result] » The Future provides a way to do asynchronous handling but doesn't necessarily have to be non- blocking
  28. Future[Result] » The async block indicates that the controller will

    return a Future[Result] » The Future provides a way to do asynchronous handling but doesn't necessarily have to be non- blocking » If a thread can't be deallocated while waiting for those other systems to respond, then it is blocking
  29. Future[Result] » The async block indicates that the controller will

    return a Future[Result] » The Future provides a way to do asynchronous handling but doesn't necessarily have to be non- blocking » If a thread can't be deallocated while waiting for those other systems to respond, then it is blocking » Order of execution doesn't matter
  30. Implications » ACID doesn't work across location/trust boundaries » No

    2-Phase commits (2PC) » No holding locks for the duration of the work
  31. Implications » Must embrace eventual consistency » Multiple workflows across

    multiple systems » Each provides a path of compensating actions
  32. Saga pattern » a Saga splits work into individual transactions

    » effects can be reversed after work has been performed and commited