Over the past few years, web-applications have started to play an increasingly important role in our lives. We expect them to be always available and the data to be always fresh. This shift into the realm of real-time data processing is now transitioning to physical devices, and Gartner predicts that the Internet of Things will grow to an installed base of 26 billion units by 2020.
Reactive web-applications are an answer to the new requirements of high-availability and resource efficiency brought by this rapid evolution. On the JVM, a set of new languages and tools has emerged that enable the development of entirely asynchronous request and data handling pipelines. At the same time, container-less application frameworks are gaining increasing popularity over traditional deployment mechanisms.
This talk is going to give you an introduction into one of the most trending reactive web-application stack on the JVM, involving the Scala programming language, the concurrency toolkit Akka and the web-application framework Play. It will show you how functional programming techniques enable asynchronous programming, and how those technologies help to build robust and resilient web-applications.
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
9. 2015: many-core
CPUs
• End of the single-core multi-core era
• Many players in the space
• Tilera, Cavium
• Adapteva Parallela
• Xeon PHI
• It's happening!
10. Too many cores?
• 1981 "640 kb ought to be enough
for anybody" ~ Bill Gates
11. Too many cores?
• 1981 "640 kb ought to be enough
for anybody" ~ Bill Gates
• 2014 "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
13. It's all in the cloud
• divide & conquer: specialized
services that do one thing well
• storage: S3
• emails: MailChimp
• monitoring: New Relic, Plumbr
• etc. etc. etc.
27. The problem with
locks
• solution workaround for a broken
conceptual model
• hard to reason about
• performance hit
28. The problem with
object-orientation
in Java
• 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
29. The Whys
1. many-core CPUs are here
2. everything is distributed
3. IoT around the corner with 26 billions devices
4. our traditional approach does not work here
32. In theory
• Functional Programming
• The Actor Model
• Evented Server Model
• Stateless architecture
• Event Sourcing
• Reactive Streams
33. In practice
• Functional Programming Scala
• The Actor Model Akka
• Evented Server Model Play
• Stateless architecture Play
• Event Sourcing Akka Persistence
• Reactive Streams Akka Streams
36. Design goals
• Full interoperability with Java
• Cut down boilerplate
• Pure object orientation & functional programming
• Move away from null
• Many-core programming
37. Core concepts of Functional
Programming
• immutability
• functions
• transforming data with functions
38. Immutability
case class Car(brand: String, position: Int)
val car = Car(brand = "DeLorean", position = 0)
val movedCar = car.copy(position = 10)
val movedCarLaterOn = car.copy(position = 30)
39. Immutability
case class Car(brand: String, position: Int)
val car = Car(brand = "DeLorean", position = 0)
val movedCar = car.copy(position = 10)
val movedCarLaterOn = car.copy(position = 30)
Work with snapshots of
state
43. 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
44. Composition
def fetchUser(id: Long): Option[User] = ...
def fetchCar(id: Long): Option[Car] = ...
val insuranceCost: Option[BigDecimal] = for {
user <- fetchUser(42)
car <- fetchCar(23)
} yield {
car.price / 10 - user.age
}
45. Composition
def fetchUser(id: Long): Future[User] = ...
def fetchCar(id: Long): Future[Car] = ...
val insuranceCost: Future[BigDecimal] = for {
user <- fetchUser(42)
car <- fetchCar(23)
} yield {
car.price / 10 - user.age
}
46. Composition
def fetchUser(id: Long): Try[User] = ...
def fetchCar(id: Long): Try[Car] = ...
val insuranceCost: Try[BigDecimal] = for {
user <- fetchUser(42)
car <- fetchCar(23)
} yield {
car.price / 10 - user.age
}
47. Composition
def fetchUser(id: Long): [User] = ...
def fetchCar(id: Long): [Car] = ...
val insuranceCost: [BigDecimal] = for {
user <- (42)
car <- (23)
} yield {
car.price / 10 - user.age
}
49. Functional
composition
• Option, Future, Try all implement
monadic operations
• set of data structures following the
same laws
• know one, know them all
• keeping things DRY
• also, it's not that scary
51. History
• 1973 "A Universal Modular Actor
Formalism for Artificial Intelligence",
Carl Hewitt, Peter Bishop and
Richard Steiger
• based on physics (quantum
physics and relativistic physics)
• 1986 First release of Erlang (Joe
Armstrong)
• 1998 Ericsson reports that the
AXD301 switch achieves an
availability of 99.9999999%
52. History
• 2010 First release of Akka (Jonas
Bonér)
• inspired by Erlang and the Actor
Model
• message-based asynchronous
concurrency toolkit
• object-oriented programming
done right
53. History
• 2010 First release of Akka (Jonas
Bonér)
• inspired by Erlang and the Actor
Model
• message-based asynchronous
concurrency toolkit
• object-oriented programming
done right
• Akka is also a mountain in Sweden
58. Sending and receiving messages
case object RevelationOfFathership
class Luke extends Actor {
def receive = {
case RevelationOfFathership =>
System.err.println("Noooooooooo")
}
}
59. Sending and receiving messages
case object RevelationOfFathership
class Luke extends Actor {
def receive = {
case RevelationOfFathership =>
System.err.println("Noooooooooo")
}
}
val luke = ActorSystem.actorOf(Props[Luke])
luke ! RevelationOfFathership
60. Supervision
class Vader extends Actor {
val troopers: ActorRef = context
.actorOf[StromTrooper]
.withRouter(
RoundRobinRouter(nrOfInstances = 8)
)
}
61. Supervision
class Vader extends Actor {
val troopers: ActorRef = context
.actorOf[StromTrooper]
.withRouter(
RoundRobinRouter(nrOfInstances = 8)
)
}
62. Supervision
class Vader extends Actor {
val troopers: ActorRef = context
.actorOf[StromTrooper]
.withRouter(
RoundRobinRouter(nrOfInstances = 8)
)
override def supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 3) {
case t: Throwable =>
log.error("StormTrooper down!",
t)
Restart
}
}
64. 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
66. 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
67. 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
68. Advantages of the evented
approach
• less threads means less memory
• better CPU utilization (reduced context switching)
• (much) higher throughputs than threaded servers
69. The Hows
1. functional programming (immutability, functions,
composition)
2. actor model
3. evented servers & stateless architecture
4. event-sourcing & reactive streams
70. Summary
• many-core & distributed systems
around the corner and there to stay
• get ready and adopt some of the
"new" tools