Date post: | 22-Jan-2018 |
Category: |
Documents |
Upload: | rahul-shukla |
View: | 326 times |
Download: | 0 times |
Akka Rahul [email protected]
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 amessage 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 : @Overridepublic 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 : @Overridepublic void preRestart(Throwable reason, Option<Object> message) throws Exception {// Handle here}
@Overridepublic void postRestart(Throwable reason) throws Exception { // Handle here}
@Overridepublic 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