Akka
Rahul Shukla
rahul.shukla@synerzip.com
Why ?
Application requirements have changed
New requirements
Apps in the 60s-90s were written for Apps today are written for
Single machines Clusters of machines
Single core processors Multicore processors
Expensive RAM Cheap RAM
Expensive disk Cheap disk
Slow networks Fast networks
Few concurrent users Lots of concurrent users
Small data sets Large data sets
Latency in seconds Latency in milliseconds
As a matter of necessity,businesses are going
Reactive
Responsive
● Real-time, engaging, rich and collaborative
○ Create an open and ongoing dialog with users
○ More efficient workflow; inspires a feeling of connectedness
○ Fully Reactive enabling push instead of pull
Elastic
● Scalability and elasticity to embrace the Cloud
○ Leverage all cores via asynchronous programming
○ Clustered servers support joining and leaving of nodes
○ More cost-efficient utilization of hardware
Resilient
● Failure is embraced as a natural state in the app lifecycle
○ Resilience is a first-class construct
○ Failure is detected, isolated, and managed
○ Applications self heal
Message-Driven
● Loosely coupled architecture, easier to extend, maintain, evolve
○ Asynchronous and non-blocking
○ Concurrent by design, immutable state
○ Lower latency and higher throughput
What?
Introducing Akka
The name comes from the goddess in the Sami
(native swedes) mythology that represented all
the wisdom and beauty in the world.
It is also the name of a beautiful mountain in
Laponia in the north part of Sweden
● Message - Driven
● Concurrency
● Scalability (Elastic)
● Fault Tolerance (Resilient)
Vision
Manage System Overload
Scale Up & Scale Out
Program at higher level
● Never think in terms of shared state, state visibility, threads,
locks, concurrent collections, thread notifications etc.
● Low level concurrency plumbing BECOMES SIMPLE
WORKFLOW - you only think about how messages flow in
the system
● You get high CPU utilization, low latency, high throughput
and scalability - FOR FREE as part of the model
● Proven and superior model for detecting and recovering
from errors
Distributable by Design
● Actors are location transparent & distributable by design
● Scale UP and OUT for free as part of the model
● You get the PERFECT FABRIC for the CLOUD
○ elastic & dynamic
○ fault-tolerant & self-healing
○ adaptive load-balancing, cluster rebalancing & actor
migration
○ build extremely loosely coupled and dynamic systems
that can change and adapt at runtime
How
Can we achieve this ?
Actor
What is an Actor ?
● Akka's unit of code organization is called an Actor
● Actors helps you create concurrent, scalable and fault-
tolerant applications
● Like Java EE servlets and session beans, Actors is a model
for organizing your code that keeps many “policy
decisions” separate from the business logic
● Actors may be new to many in the Java community, but
they are a tried-and-true concept (Hewitt 1973) used for
many years in telecom systems with 9 nines uptime
What can I use Actors for ?
● In different scenarios, an Actor may be an alternative to: -
○ a thread
○ an object instance or component
○ a callback or listener
○ a singleton or service
○ a router, load-balancer or pool
○ a Java EE Session Bean or Message-Driven Bean
Carl Hewitt’s definition
- The fundamental unit of computation that embodies:
- Processing
- Storage
- Communication
- 3 axioms - When an Actor receives a message it can:
- Create new Actors
- Send messages to Actors it knows
- Designate how it should handle the next message it
receives
Let’s Code
Define an actor
Scala : import akka.actor._
import bank.Bank.Balance
object Bank {
case class Balance(number: String)
def props(name: String): Props = { return Props(Bank(name)) }
}
case class Bank(name: String) extends AbstractLoggingActor {
def balance(number: String) = { //Do Something }
override def receive = {
case Balance(number) => balance(number)
}
}
Define an actor
Java : public class Bank extends AbstractLoggingActor {
public static Props props(String name) {
return Props.create(Bank.class, () -> new Bank(name));
}
@Override
public PartialFunction<Object, BoxedUnit> receive() {
return ReceiveBuilder
.match(Balance.class, b -> balance(b.number))
.build();}
private void balance(String number) {
//DO Something
}
}
Create an actor
• CREATE - creates a new instance of an Actor
• Extremely lightweight (2.7 Million per Gb RAM)
• Very strong encapsulation - encapsulates:
- state
- behavior
- message queue
• State & behavior is indistinguishable from each other
• Only way to observe state is by sending an actor a
message and see how it reacts
Create an actor
Scala : val system = ActorSystem("Bank")
val bank = system.actorOf(Bank.props("Central Bank"),”CBNK”)
Java :
ActorSystem system = ActorSystem.create("Bank");
ActorRef bank = system.actorOf(Bank.props("Central Bank"),”CBNK”);
Actors hierarchies
Bank
User System
/Bank
CBNK /Bank/user/CBNK
/Bank/system/Bank/user
SEND
• SEND - sends a message to an Actor
• Asynchronous and Non-blocking - Fire-forget
• Everything happens Reactively
- An Actor is passive until a message is sent to it,which
triggers something within the Actor
- Messages is the Kinetic Energy in an Actor system
- Actors can have lots of buffered Potential Energy but
can't do anything with it until it is triggered by a
message
• EVERYTHING is asynchronous and lockless
SEND
Scala : bank ! Bank.Balance(“12345”)
Java : bank.tell(new Bank.Balance(“12345”), ActorRef.noSender());
SEND
Anatomy of an Actor
● Each actor is represented by an ActorRef
● Each actor is has a mailbox and a dispatcher
● Only one message at a time is passed to the actor
REPLY
Scala : override def receive = {
case Balance(number) => sender ! "Message"
}
Java :
@Override
public PartialFunction<Object, BoxedUnit> receive() {
return ReceiveBuilder
.match(Balance.class, b -> sender().tell(“Message”,self()))
.build();}
SUPERVISE (Fault Tolerance)
SUPERVISE - manage another Actor’s failures
● Error handling in actors is handle by letting Actors
monitor (supervise) each other for failure
● This means that if an Actor crashes, a notification will
be sent to his supervisor, who can react upon the
failure
● This provides clean separation of processing and
error handling
Supervise
Scala : override def supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10,
withinTimeRange = 1 minute) {
case _: Account.OverdrawException => Resume
case _: Exception => Restart
}
Java :
@Override
public SupervisorStrategy supervisorStrategy() {
return new OneForOneStrategy(DeciderBuilder
.match(Account.OverdrawException.class, c -> SupervisorStrategy.
resume())
.match(Exception.class, c -> SupervisorStrategy.escalate())
.build());
}
Manage Failure
Scala : @throws[Exception](classOf[Exception])
override def preStart(): Unit = ???
@throws[Exception](classOf[Exception])
override def postRestart(reason: Throwable): Unit = ???
@throws[Exception](classOf[Exception])
override def postStop(): Unit = ???
Manage Failure
Java : @Override
public void preRestart(Throwable reason, Option<Object> message) throws
Exception {
// Handle here
}
@Override
public void postRestart(Throwable reason) throws Exception {
// Handle here
}
@Override
public void postStop() throws Exception {
// Handle here
}
Supervisor Strategies
● Akka ships with two highly configurable supervisor
strategies:
○ OneForOneStrategy: Only the faulty child is
affected when it fails
○ AllForOneStrategy: All children are affected when
one child fails
Supervisor Strategy Directives
● Resume: Simply resume message processing
● Restart:
○ Transparently replace affected actor(s) with new
instance(s)
○ Then resume message processing
● Stop: Stop affected actor(s)
● Escalate: Delegate the decision to the supervisor's
parent
Load Balancing (Elastic)
Concurrency vs. Parallelism
● Two or more tasks are concurrent, if the order in which
they get executed in time is not predetermined
● In other words, concurrency introduces non-determinism
● Concurrent tasks may or may not get executed in parallel
● Concurrent programming is primarily concerned with the
complexity that arises due to non-deterministic control
flow
● Parallel programming aims at improving throughput and
making control flow deterministic
Routers
Scala : context.actorOf(RoundRobinPool(5).props(SomeActor.props()),"some-actor")
Java :
getContext().actorOf(new RoundRobinPool(5).props(SomeActor.props()),"
some-actor");
Routing Strategies provided by Akka
● RandomRoutingLogic
● RoundRobinRoutingLogic
● SmallestMailboxRoutingLogic
● ConsistentHashingRoutingLogic
● BroadcastRoutingLogic
● ScatterGatherFirstCompletedRoutingLogic
● To write your own routing strategy, extend RoutingLogic:
● Attention: The implementation must be thread-safe!
Thanks

Akka (1)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
    Apps in the60s-90s were written for Apps today are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users Small data sets Large data sets Latency in seconds Latency in milliseconds
  • 6.
    As a matterof necessity,businesses are going Reactive
  • 8.
    Responsive ● Real-time, engaging,rich and collaborative ○ Create an open and ongoing dialog with users ○ More efficient workflow; inspires a feeling of connectedness ○ Fully Reactive enabling push instead of pull
  • 9.
    Elastic ● Scalability andelasticity to embrace the Cloud ○ Leverage all cores via asynchronous programming ○ Clustered servers support joining and leaving of nodes ○ More cost-efficient utilization of hardware
  • 10.
    Resilient ● Failure isembraced as a natural state in the app lifecycle ○ Resilience is a first-class construct ○ Failure is detected, isolated, and managed ○ Applications self heal
  • 11.
    Message-Driven ● Loosely coupledarchitecture, easier to extend, maintain, evolve ○ Asynchronous and non-blocking ○ Concurrent by design, immutable state ○ Lower latency and higher throughput
  • 12.
  • 13.
    The name comesfrom the goddess in the Sami (native swedes) mythology that represented all the wisdom and beauty in the world. It is also the name of a beautiful mountain in Laponia in the north part of Sweden
  • 14.
    ● Message -Driven ● Concurrency ● Scalability (Elastic) ● Fault Tolerance (Resilient) Vision
  • 15.
  • 16.
    Scale Up &Scale Out
  • 17.
  • 18.
    ● Never thinkin terms of shared state, state visibility, threads, locks, concurrent collections, thread notifications etc. ● Low level concurrency plumbing BECOMES SIMPLE WORKFLOW - you only think about how messages flow in the system ● You get high CPU utilization, low latency, high throughput and scalability - FOR FREE as part of the model ● Proven and superior model for detecting and recovering from errors
  • 19.
  • 20.
    ● Actors arelocation transparent & distributable by design ● Scale UP and OUT for free as part of the model ● You get the PERFECT FABRIC for the CLOUD ○ elastic & dynamic ○ fault-tolerant & self-healing ○ adaptive load-balancing, cluster rebalancing & actor migration ○ build extremely loosely coupled and dynamic systems that can change and adapt at runtime
  • 21.
  • 22.
  • 23.
    ● Akka's unitof code organization is called an Actor ● Actors helps you create concurrent, scalable and fault- tolerant applications ● Like Java EE servlets and session beans, Actors is a model for organizing your code that keeps many “policy decisions” separate from the business logic ● Actors may be new to many in the Java community, but they are a tried-and-true concept (Hewitt 1973) used for many years in telecom systems with 9 nines uptime
  • 24.
    What can Iuse Actors for ?
  • 25.
    ● In differentscenarios, an Actor may be an alternative to: - ○ a thread ○ an object instance or component ○ a callback or listener ○ a singleton or service ○ a router, load-balancer or pool ○ a Java EE Session Bean or Message-Driven Bean
  • 26.
  • 27.
    - The fundamentalunit of computation that embodies: - Processing - Storage - Communication - 3 axioms - When an Actor receives a message it can: - Create new Actors - Send messages to Actors it knows - Designate how it should handle the next message it receives
  • 28.
  • 29.
    Define an actor Scala: import akka.actor._ import bank.Bank.Balance object Bank { case class Balance(number: String) def props(name: String): Props = { return Props(Bank(name)) } } case class Bank(name: String) extends AbstractLoggingActor { def balance(number: String) = { //Do Something } override def receive = { case Balance(number) => balance(number) } }
  • 30.
    Define an actor Java: public class Bank extends AbstractLoggingActor { public static Props props(String name) { return Props.create(Bank.class, () -> new Bank(name)); } @Override public PartialFunction<Object, BoxedUnit> receive() { return ReceiveBuilder .match(Balance.class, b -> balance(b.number)) .build();} private void balance(String number) { //DO Something } }
  • 31.
    Create an actor •CREATE - creates a new instance of an Actor • Extremely lightweight (2.7 Million per Gb RAM) • Very strong encapsulation - encapsulates: - state - behavior - message queue • State & behavior is indistinguishable from each other • Only way to observe state is by sending an actor a message and see how it reacts
  • 32.
    Create an actor Scala: val system = ActorSystem("Bank") val bank = system.actorOf(Bank.props("Central Bank"),”CBNK”) Java : ActorSystem system = ActorSystem.create("Bank"); ActorRef bank = system.actorOf(Bank.props("Central Bank"),”CBNK”);
  • 33.
    Actors hierarchies Bank User System /Bank CBNK/Bank/user/CBNK /Bank/system/Bank/user
  • 34.
    SEND • SEND -sends a message to an Actor • Asynchronous and Non-blocking - Fire-forget • Everything happens Reactively - An Actor is passive until a message is sent to it,which triggers something within the Actor - Messages is the Kinetic Energy in an Actor system - Actors can have lots of buffered Potential Energy but can't do anything with it until it is triggered by a message • EVERYTHING is asynchronous and lockless
  • 35.
    SEND Scala : bank! Bank.Balance(“12345”) Java : bank.tell(new Bank.Balance(“12345”), ActorRef.noSender());
  • 36.
  • 37.
    Anatomy of anActor ● Each actor is represented by an ActorRef ● Each actor is has a mailbox and a dispatcher ● Only one message at a time is passed to the actor
  • 38.
    REPLY Scala : overridedef receive = { case Balance(number) => sender ! "Message" } Java : @Override public PartialFunction<Object, BoxedUnit> receive() { return ReceiveBuilder .match(Balance.class, b -> sender().tell(“Message”,self())) .build();}
  • 39.
    SUPERVISE (Fault Tolerance) SUPERVISE- manage another Actor’s failures ● Error handling in actors is handle by letting Actors monitor (supervise) each other for failure ● This means that if an Actor crashes, a notification will be sent to his supervisor, who can react upon the failure ● This provides clean separation of processing and error handling
  • 40.
    Supervise Scala : overridedef supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: Account.OverdrawException => Resume case _: Exception => Restart } Java : @Override public SupervisorStrategy supervisorStrategy() { return new OneForOneStrategy(DeciderBuilder .match(Account.OverdrawException.class, c -> SupervisorStrategy. resume()) .match(Exception.class, c -> SupervisorStrategy.escalate()) .build()); }
  • 41.
    Manage Failure Scala :@throws[Exception](classOf[Exception]) override def preStart(): Unit = ??? @throws[Exception](classOf[Exception]) override def postRestart(reason: Throwable): Unit = ??? @throws[Exception](classOf[Exception]) override def postStop(): Unit = ???
  • 42.
    Manage Failure Java :@Override public void preRestart(Throwable reason, Option<Object> message) throws Exception { // Handle here } @Override public void postRestart(Throwable reason) throws Exception { // Handle here } @Override public void postStop() throws Exception { // Handle here }
  • 43.
    Supervisor Strategies ● Akkaships with two highly configurable supervisor strategies: ○ OneForOneStrategy: Only the faulty child is affected when it fails ○ AllForOneStrategy: All children are affected when one child fails
  • 44.
    Supervisor Strategy Directives ●Resume: Simply resume message processing ● Restart: ○ Transparently replace affected actor(s) with new instance(s) ○ Then resume message processing ● Stop: Stop affected actor(s) ● Escalate: Delegate the decision to the supervisor's parent
  • 45.
  • 46.
    Concurrency vs. Parallelism ●Two or more tasks are concurrent, if the order in which they get executed in time is not predetermined ● In other words, concurrency introduces non-determinism ● Concurrent tasks may or may not get executed in parallel ● Concurrent programming is primarily concerned with the complexity that arises due to non-deterministic control flow ● Parallel programming aims at improving throughput and making control flow deterministic
  • 48.
    Routers Scala : context.actorOf(RoundRobinPool(5).props(SomeActor.props()),"some-actor") Java: getContext().actorOf(new RoundRobinPool(5).props(SomeActor.props())," some-actor");
  • 49.
    Routing Strategies providedby Akka ● RandomRoutingLogic ● RoundRobinRoutingLogic ● SmallestMailboxRoutingLogic ● ConsistentHashingRoutingLogic ● BroadcastRoutingLogic ● ScatterGatherFirstCompletedRoutingLogic ● To write your own routing strategy, extend RoutingLogic: ● Attention: The implementation must be thread-safe!
  • 50.