Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM

1,064 views

Published on

An overview of reactive technologies featuring Scala, Akka and Play

Published in: Internet
  • Be the first to comment

Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM

  1. 1. Agenda 1. Why Reactive? 2. Functional programming 3. Scala 4. Play 5. Akka
  2. 2. Who is speaking? • freelance software consultant based in Vienna • Vienna Scala User Group • web, web, web
  3. 3. Who is speaking? • freelance software consultant based in Vienna • Vienna Scala User Group • web, web, web • writing a book on reactive web- applications http://www.manning.com/ bernhardt
  4. 4. Why Reactive?
  5. 5. Welcome to 2015 It's 2015! And yet we don't have flying cars...
  6. 6. But we have many- core CPUs • Tilera, Cavium • Adapteva Parallela • Xeon PHI • It's happening!
  7. 7. Too many cores? • "640 kb ought to be enough for anybody" ~ Bill Gates
  8. 8. Too many cores? • "640 kb ought to be enough for anybody" ~ Bill Gates • "4 cores ought to be enough for anybody" ~ Linus Torvalds1 1 http://highscalability.com/blog/2014/12/31/linus-the-whole-parallel- computing-is-the-future-is-a-bunch.html
  9. 9. Programming with many cores • serial approach does not work • asynchronous programming with inappropriate tools does not work drives people insane • we need (and already have) new abstractions • we have to re-evaluate the use of our old abstractions
  10. 10. The problem with mutable state car.setPosition(0); car.setPosition(10);
  11. 11. The problem with mutable state
  12. 12. The problem with mutable state • there is no notion of time, only an illusion thereof • changes to a mutable model only make sense locally if nobody is watching • the larger the scope, the harder it gets to prevent inconsistencies
  13. 13. The problem with locks • solution workaround for a broken conceptual model • hard to reason about • performance hit
  14. 14. Distribution is necessary * * unless you have a lot of money
  15. 15. Let's make things even more complicated: programming with many nodes • scaling out to handle large loads • scaling out / replication to handle node failure
  16. 16. Let's make things even more complicated: programming with many nodes • scaling out to handle large loads • scaling out / replication to handle node failure • problem: networks fail
  17. 17. Failure is inevitable • Jepsen series3 • CAP theorem • transactions don't really work that way in distributed systems 3 http://aphyr.com
  18. 18. Hard problem to solve • Paxos: Consensus solving protocols • CQRS: Command Query Responsibility Segregation • CRDTs: Commutative Replicated Data Types
  19. 19. Functional programming to the rescue
  20. 20. Imperative programming In imperative programming you describe how something is done
  21. 21. Imperative programming In imperative programming you describe how something is done Example: List<User> users = ... List<User> minors = new ArrayList<User>(); List<User> majors = new ArrayList<User>(); for(int i = 0; i < users.size(), i++;) { User u = users.get(i); if(u.getAge() < 18) { minors.add(u); } else { majors.add(u); } }
  22. 22. Declarative programming In declarative programming you describe what you want to get
  23. 23. Declarative programming In declarative programming you describe what you want to get Example: val (minors, majors) = users.partition(_.age < 18)
  24. 24. Declarative programming In declarative programming you describe what you want to get Example: val (minors, majors) = users.partition(_.age < 18) Declarative programming is like driving with a GPS navigation system You can do without, but it's so comfortable
  25. 25. Core concepts of FP • immutability • functions • transforming data with functions
  26. 26. Immutability case class Car(brand: String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  27. 27. Immutability case class Car(brand: String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  28. 28. Immutability case class Car(brand: String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  29. 29. Functions and higher-order functions val (minors, majors) = users.partition(_.age < 18)
  30. 30. Functions and higher-order functions val isMinor = (age: Int) => age < 18 val (minors, majors) = users.partition(isMinor)
  31. 31. Functions and higher-order functions val isMinor = (age: Int) => age < 18 val (minors, majors) = users.partition(isMinor) Moving behaviour around instead of moving data around
  32. 32. Transforming data val addresses = users.filter(_.age > 18) .map(_.address) .sortBy(_.city) Goal: To build increasingly complex behaviour through a series of transformations / by composing functions
  33. 33. Composition def fetchUser(id: Long): Option[User] = ... def fetchCar(id: Long): Option[Car] = ... val carPrice: Option[BigDecimal] = for { user <- fetchUser(42) car <- fetchCar(23) } yield { user.age + car.price }
  34. 34. Composition def fetchUser(id: Long): Future[User] = ... def fetchCar(id: Long): Future[Car] = ... val carPrice: Future[BigDecimal] = for { user <- fetchUser(42) car <- fetchCar(23) } yield { user.age + car.price }
  35. 35. Composition def fetchUser(id: Long): Try[User] = ... def fetchCar(id: Long): Try[Car] = ... val carPrice: Try[BigDecimal] = for { user <- fetchUser(42) car <- fetchCar(23) } yield { user.age + car.price }
  36. 36. Composition def fetchUser(id: Long): [User] = ... def fetchCar(id: Long): [Car] = ... val carPrice: [BigDecimal] = for { user <- (42) car <- (23) } yield { user.age + car.price }
  37. 37. Maths FTW! • Option, Future, Try all implement monadic operations2 • set of data structures following the same laws • know one, know them all • keeping things DRY • also, it's not that scary 2 https://www.haskell.org/haskellwiki/Monad_tutorials_timeline
  38. 38. Scala
  39. 39. History • Martin Odersky, EPFL • first release in 2003 • Typesafe Inc.
  40. 40. Design goals • Full interoperability with Java • Cut down boilerplate • Pure object orientation & functional programming • Move away from null • Many-core programming
  41. 41. If I were to pick a language today other than Java, it would be Scala. — James Gosling
  42. 42. Scala in Vienna • Monthly Meetup • http://scala-vienna.org • Next meetup on 18th of February
  43. 43. Play
  44. 44. Play history • MVC framework, inspired by RoR, Django, Symfony • Zenexity • first version released in 2009 • version 2.0 released in 2012, core rewritten in Scala
  45. 45. Design Principles • everything is compiled • non-blocking I/O • controller actions are functions (request => response) • "share nothing" => horizontal scalability
  46. 46. Threaded servers • like a train station with multiple tracks • station chief decides which trains go on which platform • if there are more trains than platforms, trains queue up • if too many trains are queuing up, huge delays occur and passengers go home
  47. 47. Evented servers • like a waiter in a restaurant • runs back and forth between tables and the kitchen • does only small tasks that do not take much time • one server can each serve many tables at once
  48. 48. Advantages of the evented approach • less threads means less memory • better CPU utilization (reduced context switching) • (much) higher throughputs than threaded servers
  49. 49. History • first release in January 2010 • based on the Actor model (Erlang) • message-based asynchronous concurrency toolkit • object-oriented programming done right
  50. 50. History • first release in January 2010 • based on the Actor model (Erlang) • message-based asynchronous concurrency toolkit • object-oriented programming done right • Akka is also a mountain in Sweden
  51. 51. Actors • lightweight objects • send and receive messages (mailbox) • can have children (supervision)
  52. 52. Sending and receiving messages case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } }
  53. 53. Sending and receiving messages case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } } val audrey = ActorSystem.actorOf(Props[Audrey]) audrey ! Script(breakfastAtTiffany)
  54. 54. Supervision class HollyCrazyCatLady extends Actor { lazy val cats: ActorRef = context .actorOf[Cat] .withRouter( RoundRobinRouter(nrOfInstances = 42) ) }
  55. 55. Supervision class HollyCrazyCatLady extends Actor { lazy val cats: ActorRef = context .actorOf[Cat] .withRouter( RoundRobinRouter(nrOfInstances = 42) ) override def supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 3) { case t: Throwable => log.error("A cat had a problem!", t) Restart } }
  56. 56. Actors out there • remoting • clustering • persistent actors event sourcing
  57. 57. CQRS • high level: separate writes & reads (performance) • transform and store everything as events (write only) • transform into query model in a separate store Immutability (again!)
  58. 58. Summary • many-core is here to stay • FP is essential to take advantage of many-core systems
  59. 59. Summary • many-core is here to stay • FP is essential to take advantage of many-core systems • Play and Akka make it possible to build web-applications that can scale in and out
  60. 60. Thank you http://www.manning.com/bernhardt code mlbernhardt 50% discount Questions? http://scala-vienna.org 18th of February Join the dark side, we have free drinks

×