Agenda
1. Why Reactive?
2. Functional programming
3. Scala
4. Play
5. Akka
Who is speaking?
• freelance software consultant based
in Vienna
• Vienna Scala User Group
• web, web, web
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
Why Reactive?
Welcome to 2015
It's 2015!
And yet we don't have flying cars...
But we have many-
core CPUs
• Tilera, Cavium
• Adapteva Parallela
• Xeon PHI
• It's happening!
Too many cores?
• "640 kb ought to be enough for
anybody" ~ Bill Gates
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
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
The problem with mutable state
car.setPosition(0);
car.setPosition(10);
The problem with mutable state
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
The problem with
locks
• solution workaround for a broken
conceptual model
• hard to reason about
• performance hit
Distribution is
necessary *
* unless you have a lot of money
Let's make things
even more
complicated:
programming with
many nodes
• scaling out to handle large loads
• scaling out / replication to handle
node failure
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
Failure is inevitable
• Jepsen series3
• CAP theorem
• transactions don't really work that
way in distributed systems
3
http://aphyr.com
Hard problem to
solve
• Paxos: Consensus solving protocols
• CQRS: Command Query
Responsibility Segregation
• CRDTs: Commutative Replicated
Data Types
Functional
programming to the
rescue
Imperative
programming
In imperative programming you
describe how something is done
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);
}
}
Declarative
programming
In declarative programming you
describe what you want to get
Declarative
programming
In declarative programming you
describe what you want to get
Example:
val (minors, majors) = users.partition(_.age < 18)
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
Core concepts of FP
• immutability
• functions
• transforming data with functions
Immutability
case class Car(brand: String, position: Int)
val car = Car(brand = "DeLorean", position = 0)
val movedCar = car.copy(position = 10)
Immutability
case class Car(brand: String, position: Int)
val car = Car(brand = "DeLorean", position = 0)
val movedCar = car.copy(position = 10)
Immutability
case class Car(brand: String, position: Int)
val car = Car(brand = "DeLorean", position = 0)
val movedCar = car.copy(position = 10)
Functions and higher-order
functions
val (minors, majors) = users.partition(_.age < 18)
Functions and higher-order
functions
val isMinor = (age: Int) => age < 18
val (minors, majors) = users.partition(isMinor)
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
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
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
}
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
}
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
}
Composition
def fetchUser(id: Long): [User] = ...
def fetchCar(id: Long): [Car] = ...
val carPrice: [BigDecimal] = for {
user <- (42)
car <- (23)
} yield {
user.age + car.price
}
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
Scala
History
• Martin Odersky, EPFL
• first release in 2003
• Typesafe Inc.
Design goals
• Full interoperability with Java
• Cut down boilerplate
• Pure object orientation & functional programming
• Move away from null
• Many-core programming
If I were to pick a
language today other
than Java, it would be
Scala.
— James Gosling
Scala in Vienna
• Monthly Meetup
• http://scala-vienna.org
• Next meetup on 18th of February
Play
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
Design Principles
• everything is compiled
• non-blocking I/O
• controller actions are functions (request => response)
• "share nothing" => horizontal scalability
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
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
Advantages of the evented
approach
• less threads means less memory
• better CPU utilization (reduced context switching)
• (much) higher throughputs than threaded servers
History
• first release in January 2010
• based on the Actor model (Erlang)
• message-based asynchronous
concurrency toolkit
• object-oriented programming done
right
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
Actors
• lightweight objects
• send and receive messages (mailbox)
• can have children (supervision)
Sending and receiving messages
case class Script(text: String)
class AudreyHepburn extends Actor {
def receive = {
case Script(text) =>
read(text)
}
}
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)
Supervision
class HollyCrazyCatLady extends Actor {
lazy val cats: ActorRef = context
.actorOf[Cat]
.withRouter(
RoundRobinRouter(nrOfInstances = 42)
)
}
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
}
}
Actors out there
• remoting
• clustering
• persistent actors event sourcing
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!)
Summary
• many-core is here to stay
• FP is essential to take advantage of
many-core systems
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
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

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

  • 2.
    Agenda 1. Why Reactive? 2.Functional programming 3. Scala 4. Play 5. Akka
  • 3.
    Who is speaking? •freelance software consultant based in Vienna • Vienna Scala User Group • web, web, web
  • 4.
    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
  • 5.
  • 6.
    Welcome to 2015 It's2015! And yet we don't have flying cars...
  • 7.
    But we havemany- core CPUs • Tilera, Cavium • Adapteva Parallela • Xeon PHI • It's happening!
  • 8.
    Too many cores? •"640 kb ought to be enough for anybody" ~ Bill Gates
  • 9.
    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
  • 11.
    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
  • 12.
    The problem withmutable state car.setPosition(0); car.setPosition(10);
  • 13.
    The problem withmutable state
  • 14.
    The problem with mutablestate • 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
  • 15.
    The problem with locks •solution workaround for a broken conceptual model • hard to reason about • performance hit
  • 16.
    Distribution is necessary * *unless you have a lot of money
  • 17.
    Let's make things evenmore complicated: programming with many nodes • scaling out to handle large loads • scaling out / replication to handle node failure
  • 18.
    Let's make things evenmore complicated: programming with many nodes • scaling out to handle large loads • scaling out / replication to handle node failure • problem: networks fail
  • 19.
    Failure is inevitable •Jepsen series3 • CAP theorem • transactions don't really work that way in distributed systems 3 http://aphyr.com
  • 20.
    Hard problem to solve •Paxos: Consensus solving protocols • CQRS: Command Query Responsibility Segregation • CRDTs: Commutative Replicated Data Types
  • 21.
  • 22.
    Imperative programming In imperative programmingyou describe how something is done
  • 23.
    Imperative programming In imperative programmingyou 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); } }
  • 24.
    Declarative programming In declarative programmingyou describe what you want to get
  • 25.
    Declarative programming In declarative programmingyou describe what you want to get Example: val (minors, majors) = users.partition(_.age < 18)
  • 26.
    Declarative programming In declarative programmingyou 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
  • 27.
    Core concepts ofFP • immutability • functions • transforming data with functions
  • 28.
    Immutability case class Car(brand:String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  • 29.
    Immutability case class Car(brand:String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  • 30.
    Immutability case class Car(brand:String, position: Int) val car = Car(brand = "DeLorean", position = 0) val movedCar = car.copy(position = 10)
  • 31.
    Functions and higher-order functions val(minors, majors) = users.partition(_.age < 18)
  • 32.
    Functions and higher-order functions valisMinor = (age: Int) => age < 18 val (minors, majors) = users.partition(isMinor)
  • 33.
    Functions and higher-order functions valisMinor = (age: Int) => age < 18 val (minors, majors) = users.partition(isMinor) Moving behaviour around instead of moving data around
  • 34.
    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
  • 35.
    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 }
  • 36.
    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 }
  • 37.
    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 }
  • 38.
    Composition def fetchUser(id: Long):[User] = ... def fetchCar(id: Long): [Car] = ... val carPrice: [BigDecimal] = for { user <- (42) car <- (23) } yield { user.age + car.price }
  • 39.
    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
  • 40.
  • 41.
    History • Martin Odersky,EPFL • first release in 2003 • Typesafe Inc.
  • 42.
    Design goals • Fullinteroperability with Java • Cut down boilerplate • Pure object orientation & functional programming • Move away from null • Many-core programming
  • 44.
    If I wereto pick a language today other than Java, it would be Scala. — James Gosling
  • 45.
    Scala in Vienna •Monthly Meetup • http://scala-vienna.org • Next meetup on 18th of February
  • 46.
  • 47.
    Play history • MVCframework, inspired by RoR, Django, Symfony • Zenexity • first version released in 2009 • version 2.0 released in 2012, core rewritten in Scala
  • 48.
    Design Principles • everythingis compiled • non-blocking I/O • controller actions are functions (request => response) • "share nothing" => horizontal scalability
  • 49.
    Threaded servers • likea 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
  • 50.
    Evented servers • likea 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
  • 51.
    Advantages of theevented approach • less threads means less memory • better CPU utilization (reduced context switching) • (much) higher throughputs than threaded servers
  • 53.
    History • first releasein January 2010 • based on the Actor model (Erlang) • message-based asynchronous concurrency toolkit • object-oriented programming done right
  • 54.
    History • first releasein 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
  • 55.
    Actors • lightweight objects •send and receive messages (mailbox) • can have children (supervision)
  • 59.
    Sending and receivingmessages case class Script(text: String) class AudreyHepburn extends Actor { def receive = { case Script(text) => read(text) } }
  • 60.
    Sending and receivingmessages 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)
  • 61.
    Supervision class HollyCrazyCatLady extendsActor { lazy val cats: ActorRef = context .actorOf[Cat] .withRouter( RoundRobinRouter(nrOfInstances = 42) ) }
  • 62.
    Supervision class HollyCrazyCatLady extendsActor { 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 } }
  • 63.
    Actors out there •remoting • clustering • persistent actors event sourcing
  • 64.
    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!)
  • 65.
    Summary • many-core ishere to stay • FP is essential to take advantage of many-core systems
  • 66.
    Summary • many-core ishere 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
  • 67.
    Thank you http://www.manning.com/bernhardt code mlbernhardt50% discount Questions? http://scala-vienna.org 18th of February Join the dark side, we have free drinks