akka-intro-slides



akka-intro-slides

0 0


akka-intro-slides


On Github markusjura / akka-intro-slides

Introducing Akka

Markus Jura

About me

  • Trainer @Typesafe
  • Living in Hamburg
  • Co-Founder of testmunk
  • 3 years Scala, 10 years Java background

Akka (Áhkká)

The name comes from the goddess in the Sami (Native swedes) mythology that represents all the wisdom and beauty in the world.

Akka (Áhkká)

It is also the name of a beautiful mountain in Laponia in the north part of Sweden.

What is Akka?

Akka is a toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on the JVM. akka.io

Akka's Value Proposition

A single unified programming model for

  • simpler concurrency
  • simpler distribution
  • simpler fault tolerance

Manage System Overload

Scale Up & Scale Out

Program at Higher Level I

  • Never think about
    • Shared state
    • Threads
    • Locks
  • Low level concurrency becomes simple
    • Think how messages flow in the system

Program at Higher Level II

  • High CPU utilization
  • Low latency
  • High troughput
  • Scalability

Distributable by Design I

  • Everything in Akka is distributed by default
    • Going from local to remote by configuration

Distributable by Design II

  • Perfect Programming Model for the Cloud
    • Elastic & dynamic
    • Fault-tolerant & self-healing
    • Load-Balancing & cluster rebalancing
  • Loosly coupled and dynamic systems that can change and adapt at runtime

Selection of Akka Production Users

How can we achieve this?

Let's use Actors!

Carl Hewitt's definition?

  • The fundamental unit of computation that embodies:
    • Processing
    • Storage
    • Communication
  • Akka:
    • Processing → Behavior
    • Storage → State

What is an Actor?

  • Java / Scala Class
    • With a mailbox (Queue)
    • Receives messages
    • Only one message at a time is handled
    • Extremely lightweight (400 Bytes / 2.7 Million per GB)

Now - if we replace

Everthing will still hold for both local and distributed Actors

What can I use Actors for?

  • Can be an alternative to:
    • Thread
    • Object instance or component
    • Callback or listener
    • Singleton or service

What can I use Actors for?

  • Can be an alternative to:
    • Router, load-Balancer or pool
    • Java EE Session Bean or Message-Driven Bean
    • Finite State Machine (FSM)

Actor in Java

// Message Protocol
public static class Greeting implements Serializable {
  public final String who;
  public Greeting(String who) { this.who = who; }
}

public class GreetingActor extends UntypedActor {
  // Put mutable state in here..

  public void onReceive(Object message) {
    if(message instanceof Greeting)
      System.out.println("Hello " + ((Greeting) message).who);
  }
}

Actor in Scala

// Message Protocol
case class Greeting(who: String)

class GreetingActor extends Actor {
  // Put mutable state in here..

  def receive = {
    // Define the behavior here..
    case Greeting(who) => println(s"Hello $who")
  }
}

4 Core Actor Operations

  • When an Actor handles a Message, it can
  • Create → Create new Actors
  • Send → Send messages to other Actors
  • Become → Change the behavior for handling the next message
  • Supervise → Manage another Actors failure

1. Create

  • Each Actor is repesented by an ActorRef
  • You never get access to an Actor instance
  • An Actor reference let's you send messages to an Actor

Create an Actor (Java)

// Creates an Actor system
final ActorSystem system = ActorSystem.create("MySystem");

final ActorRef greeter = 
  system.actorOf(new Props(GreetingActor.class), "greeter");
//       ^^ Create   ^^ Actor configuration      ^^ Actor name

Actors can form hierarchies

Actors can form hierarchies

Actors Name Resolution

2. Send

  • To send a message to an actor, you need a Actor reference
  • Asynchronous and Non-blocking (Fire-and-forget)

  • Attention: Messages must be immutable!

  • Best practice:
    • Use case objects and/or case classes
    • Define the message protocol in the companion object of the actor

Troughput on a Single Machine

+50 million messages per second

Link to Performance Test

Send Message (Java / Scala)

Java

greeter.tell(new Greeting("Charlie"), ActorRef.noSender());

Scala

greeter ! Greeting("Charlie")

Reply (Java)

class SomeActor extends UntypedActor {
  public void onReceive(Object msg) {
    if(msg instanceof User) {
      User user = (User) msg;
      // Reply to sender
      getSender().tell("Hi " + user.name, getSelf());
    }
  }
}

Reply (Scala)

class SomeActor extends Actor {
  def receive = {
    // Reply to sender
    case User(name) => sender ! (s"Hi $name")
  }
}

Remote Deployment

akka {
  actor {
    # Configure Remote Provider
    provider = akka.remote.RemoteActorRefProvider
    deployment {
      /greeter {
        # Define Remote Path
        remote = akka://MySystem@machine1:2552
      }
    }
  }
}
  • Just feed the ActorSystem with this configuration → Zero code changes
  • You can configure the remote deployment programmatically as well

3. Become

  • Dynamically redefining Actors behavior
  • Triggered by receiving a message
  • Will now react differently to the messages it receives

Why would I want to do that?

  • Implement a Finite State Machine (FSM)
  • Let a highly contended Actor adaptively transform himself into an Actor Pool or a Router
  • Implement graceful degradation (Fehlertoleranz)
  • Spawn up (empty) generic Worker Actors that can become whatever the Master currently needs

Become (Java)

Procedure<Object> happy = new Procedure<Object>() {
  public void apply(Object msg) {
    if(msg instanceof HappyMessage) {
      HappyMessage happyMsg = (HappyMessage) msg;
      ...
    }
  }
});

public void onReceive(Object msg) {
  if(msg instanceof HappyMessage)
    getContext.become(happy);
}

Become (Scala)

def happy: Receive = {
  case HappyMessage => ...
}

def receive = {
  case HappyMessage => context become(happy)
}

Load Balancing

Routers (Java)

Programmatically

int nrOfInstances = 5;
ActorRef router =
  system.actorOf(new Props(SomeActor)
    .withRouter(new RoundRobinRouter(nrOfInstances)));

Routers (Java)

Configuration

akka.actor.deployment {
  /myRouter {
    router = round-robin
    nr-of-instances = 5
  }
}

Java

ActorRef router =
  system.actorOf(new Props(SomeActor)
    .withRouter(new FromConfig(), "myRouter");

Router with Resizer (Java)

int lowerBound = 2;
int upperBound = 15;
DefaultResizer resizer = new DefaultResizer(lowerBound, upperBound);

ActorRef routerWithResizer = system.actorOf(
  new Props(SomeActor.class)
    .withRouter(new RoundRobinRouter(resizer)));

Resizer can be definied in configuration file as well

Failure Management in Java/C/C# etc.

Failure Management in Java/C/C# etc.

  • Caller handles the failure
  • This leads to defensive programming with:
    • Error handling tangled with business logic
    • Scattered all over the code base

Failure Management in Akka

  • Supervisor handles failure
    • Actor throws exception → Supervisor react on failure
  • Callers need not care (they can't anyway)
  • Clean separation of processing and error handling

Let's take a standard OO application

Which components have critical important state and explicit error handling?

Error Handling in Akka

Error Handling in Akka

Supervisor Strategy

  • Every Actor has a default supervisor strategy

    • ActorInitializationException → Stop
    • ActorKilledException → Stop
    • Exception → Restart
    • Throwable → Escalate
    • Otherwise → Escalate
  • Strategy can be overriden

Override Supervisor Strategy (Java)

public class Supervisor extends UntypedActor {
  private static SupervisorStrategy strategy =
    new OneForOneStrategy(10, Duration.create("1 minute"),
      new Function<Throwable, Directive>() {
        @Override public Directive apply(Throwable t) {
          if (t instanceof ArithmeticException)       
            return resume();
          else if (t instanceof NullPointerException) 
            return restart();
          else                                        
            return escalate();
        }
      });
...

Override Supervisor Strategy (Java)

...

  @Override 
  public SupervisorStrategy supervisorStrategy() {
    return strategy;
  }
}

Override Supervisor Strategy (Scala)

class Supervisor extends Actor {
  override val supervisorStrategy = OneForOneStrategy(
      maxNrOfRetries = 10, withinTimeRange = 1 minute) {
    case _: ArithmeticException  => Resume
    case _: NullPointerException => Restart
    case _: Exception            => Escalate
  }
}

This was

Akka

Well.. it's a start..

We have much more

Get It and Learn More