60
Build Cloud Applications with Akka and Heroku Havoc Pennington, Typesafe @havocp

Build Cloud Applications with Akka and Heroku

Embed Size (px)

Citation preview

Page 1: Build Cloud Applications with Akka and Heroku

Build Cloud Applications with Akka

and Heroku

Havoc Pennington, Typesafe

@havocp

Page 2: Build Cloud Applications with Akka and Heroku

Safe Harbor

Safe harbor statement under the Private Securities Litigation Reform Act of 1995:

This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if

any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-

looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of

product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of

management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments

and customer contracts or use of our services.

The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our

service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth,

interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other l itigation, risks associated

with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain,

and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling

non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the

financial results of salesforce.com, inc. is included in our annual report on Form 10-Q for the most recent fiscal quarter ended July 31, 2012. This

documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site.

Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may

not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently

available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.

Page 3: Build Cloud Applications with Akka and Heroku

What does Typesafe do?

Modernizing development on the Java Virtual Machine

– Scala: practical, superior alternative to Java with incremental migration path

– Akka: proven Actor model gives horizontal scale for both Java and Scala,

without the pain points of explicit threads

– Play: popular Rails-style convention-over-configuration lightweight web

framework for both Java and Scala

– All supported on Heroku, a cloud platform with the same developer-friendly point

of view

3

Developer-friendly, horizontally scalable,

with a pragmatic path to adoption

Page 4: Build Cloud Applications with Akka and Heroku

This Talk

This talk introduces Akka, an actor-based middleware

– Will assume that you know Java

– What is Akka and when would you use it?

– Will briefly introduce the Heroku architecture and how it can combine with Akka

to build scalable applications

4

Page 5: Build Cloud Applications with Akka and Heroku

Getting to Know You

How many of you are already familiar with

– Actor model

– Akka

– Heroku

=> Any specific topics you hope to hear about in this talk?

5

Page 6: Build Cloud Applications with Akka and Heroku

Talk Overview

1. The high level: what's Akka / what are actors

2. Intro to the Akka API

3. A few best practices for Actors

4. Heroku-specific notes and a simple Heroku example

6

Page 7: Build Cloud Applications with Akka and Heroku

What is Akka?

• An application-organizing tool to simplify:

– concurrency

– fault tolerance

– scale-out / distribution

• An implementation of the “Actor model”

– The actor model is an alternative to explicit threads, originally used in the highly reliable Erlang

environment

• An API for both Java and Scala

– Many people use Akka but not Scala, even though Akka is written in Scala.

• Small

– core is just one no-dependencies jar

(More detail on all of these coming up...)

Page 8: Build Cloud Applications with Akka and Heroku

Selection of Akka Production Users

Page 9: Build Cloud Applications with Akka and Heroku

What is an “Actor”?

An object with state

Which receives one message at a time

(one thread at a time)

Page 10: Build Cloud Applications with Akka and Heroku

A Simple Code Example

public class HelloWorldActor extends UntypedActor {

public void onReceive(Object msg) {

getSender().tell(((String) msg) + “ World”);

}

}

class HelloWorldActor extends Actor {

def receive = {

case msg : String => sender ! (msg + “ World”)

}

}

... in Java:

... in Scala:

Page 11: Build Cloud Applications with Akka and Heroku

Actors can be seen as

Virtual Machines (nodes)

in Cloud Computing

Page 12: Build Cloud Applications with Akka and Heroku

Encapsulated and

decoupled black

boxes...

Page 13: Build Cloud Applications with Akka and Heroku

... managing their own

memory and behavior

Page 14: Build Cloud Applications with Akka and Heroku

Communicating with

asynchronous non-

blocking messages

Page 15: Build Cloud Applications with Akka and Heroku

Now if we replace

with Actor

EVERYTHING will STILL HOLD for both LOCAL and

DISTRIBUTED Actors

Page 16: Build Cloud Applications with Akka and Heroku

Actors and Servers

You can think of an actor as a network service...

...if you could implement a network service in a few lines of code and

have 2.7 million of them per gigabyte of RAM.

Page 17: Build Cloud Applications with Akka and Heroku

Actors ...

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.

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.

Unlike servlets and session beans, Actors are lightweight (< 300 bytes, no

thread-per) and dynamic (create/destroy them easily in code)

Page 18: Build Cloud Applications with Akka and Heroku

Actors can replace...

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

Page 19: Build Cloud Applications with Akka and Heroku

Solution for Concurrent Programming

• Developer writes an object, called an Actor, which handles messages.

• Each actor instance runs in only one thread at a time, so no synchronization is

required for actor state.

• Akka dispatcher schedules actors on threads – or even on multiple machines

– as needed. Can have millions of actors, an actor does not “use up” a thread.

• Mutable state is safely single-threaded.

• Easier for programmers to create reliable concurrent processing.

• Many sources of contention, races, locking and dead-locks are removed.

• No need to use locks or java.util.concurrent – at all. Even though you're

using mutable state, it's encapsulated in actors.

19

Page 20: Build Cloud Applications with Akka and Heroku

Separation of Concerns

• “Business logic” does not concern itself with the

concurrency mechanism or scheduling. Just implement

what you'd like to happen in response to each message.

•Outside your business logic, configure for example: – Dispatch and execution (thread pool, event loop)

– Fault tolerance (what happens when an actor throws an exception?)

– Remoting

– Load balancing

20

Page 21: Build Cloud Applications with Akka and Heroku

So That's What Actors Are...

Next up, Akka details: assembling actors, messages, ActorRef, ActorSystem,

supervision, and remoting into an application.

Two questions about what you've seen so far?

public class HelloWorldActor extends UntypedActor {

public void onReceive(Object msg) {

getSender().tell(((String) msg) + “ World”);

}

}

class HelloWorldActor extends Actor {

def receive = {

case msg : String => sender ! (msg + “ World”)

}

}

Page 22: Build Cloud Applications with Akka and Heroku

Touring an Akka Application

Page 23: Build Cloud Applications with Akka and Heroku

All the code.

public class Greeting implements Serializable {

public final String who;

public Greeting(String who) { this.who = who; }

}

public class GreetingActor extends UntypedActor {

LoggingAdapter log = Logging.getLogger(getContext().system(), this);

public void onReceive(Object message) throws Exception {

if (message instanceof Greeting)

log.info("Hello " + ((Greeting) message).who);

}

}

}

ActorSystem system = ActorSystem.create("MySystem");

ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");

greeter.tell(new Greeting("Charlie Parker"));

Explanation coming up...

Page 24: Build Cloud Applications with Akka and Heroku

The same in Scala...

case class Greeting(who: String)

class GreetingActor extends Actor with ActorLogging {

def receive = {

case Greeting(who) => log.info("Hello " + who)

}

}

val system = ActorSystem("MySystem")

val greeter = system.actorOf(Props[GreetingActor], name = "greeter")

greeter ! Greeting("Charlie Parker")

Explanation coming up...

Page 25: Build Cloud Applications with Akka and Heroku

ActorSystem

Every Akka application instantiates at least one ActorSystem

Akka has no global state; all state is associated with the ActorSystem

The ActorSystem includes:

• a configuration

• the dispatcher (thread pool)

• a hierarchical tree of actors

Page 26: Build Cloud Applications with Akka and Heroku

Unpacking Actor Creation

You may have noticed:

ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");

• Props defines how to create an actor

• “greeter” is the name of the actor in the hierarchy

• ActorRef is a sort of “smart pointer” handle...

Page 27: Build Cloud Applications with Akka and Heroku

ActorRef

Because actors may be relocated in a cluster, or restarted if they fail,

you NEVER access the Actor itself.

Instead, actors are created inside an ActorRef, which always refers to

the same “conceptual” actor even if that actor is relocated or

restarted.

ActorRef ensures safety: you can send messages and that's all.

public class GreetingActor extends UntypedActor {

ActorRef contains an instance of this Actor subclass

Page 28: Build Cloud Applications with Akka and Heroku

Messages go through the ActorRef

ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");

greeter.tell(new Greeting("Charlie Parker"));

val greeter = system.actorOf(Props[GreetingActor], name = "greeter")

greeter ! Greeting("Charlie Parker")

Page 29: Build Cloud Applications with Akka and Heroku

Messages

Should be immutable unless you want to have problems.

Should be serializable to enable remoting.

Can be any object. Strings for quick-and-dirty demos. Scala case

classes are perfect, in Java there's a little more work.

public class Greeting implements Serializable {

public final String who;

public Greeting(String who) { this.who = who; }

}

case class Greeting(who: String)

Page 30: Build Cloud Applications with Akka and Heroku

Hierarchy

A

B

Bar Foo

C

B E

A

D

C

/Foo

/Foo/A

/Foo/A/B

/Foo/A/D

Page 31: Build Cloud Applications with Akka and Heroku

Building Hierarchy

From inside one actor, you just create another actor. Use:

context.actorOf(..., “foo”)

Rather than:

system.actorOf(..., “foo”)

“context” is a field the Actor base class provides to its subclasses.

Best practice: avoid toplevel actors when possible.

Page 32: Build Cloud Applications with Akka and Heroku

Supervision

When actors create children, they become the fault handlers for

those children. (It's just like a real family!)

Parents are notified when their children fail, so they can take

action.

Why?

Page 33: Build Cloud Applications with Akka and Heroku

Handling Failure in Typical OO Code

Each thread has to handle errors and “keep itself alive”

No global organization of error handling ...

• defensive programming

• tangled with business logic

• scattered around the code

Page 34: Build Cloud Applications with Akka and Heroku

Which components have critically important state and

explicit error handling?

Page 35: Build Cloud Applications with Akka and Heroku
Page 36: Build Cloud Applications with Akka and Heroku

Supervision Factors Out Fault Handling

“Let it crash” philosophy; let the supervisor deal with it

Page 37: Build Cloud Applications with Akka and Heroku

Error

Kernel

Page 38: Build Cloud Applications with Akka and Heroku

class Supervisor extends UntypedActor {

private SupervisorStrategy strategy = new OneForOneStrategy(

10,

Duration.parse("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 public SupervisorStrategy supervisorStrategy() {

return strategy;

}

ActorRef worker = context.actorOf(new Props(Worker.class));

public void onReceive(Object message) throws Exception {

if (message instanceof Integer) worker.forward(message);

}

}

Java Supervisor

Page 39: Build Cloud Applications with Akka and Heroku

class Supervisor extends Actor {

override val supervisorStrategy =

OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {

case _: ArithmeticException => Resume

case _: NullPointerException => Restart

case _: Exception => Escalate

}

val worker = context.actorOf(Props[Worker])

def receive = {

case n: Int => worker forward n

}

}

Scala Supervisor

Page 40: Build Cloud Applications with Akka and Heroku

class Worker extends Actor {

...

override def preRestart(

reason: Throwable, message: Option[Any]) = {

... // clean up before restart

}

override def postRestart(reason: Throwable) = {

... // init after restart

}

}

Supervisee Hooks

Page 41: Build Cloud Applications with Akka and Heroku

Remoting

Remote actors have a different kind of ActorRef

(remember, ActorRef's job is to abstract the Actor instance and its location)

An actor can be made remote in config, with no code changes:

akka {

actor {

provider = akka.remote.RemoteActorRefProvider

deployment {

/Greeter {

remote = akka://MySystem@hostname1:2552

}

}

}

}

(also possible to do it in code)

Page 42: Build Cloud Applications with Akka and Heroku

Changing Behavior

When an actor gets a message, it may choose to change its behavior

(i.e. adopt a new message handler)

context.become(new Procedure[Object]() {

void apply(Object msg) {

// new body

if (msg instanceof NewMessage) {

NewMessage newMsg = (NewMessage)msg;

...

}

}

});

context become {

// new body

case NewMessage =>

...

}

Java

Scala

Page 43: Build Cloud Applications with Akka and Heroku

Why Change Behavior?

Ideas

1. State machine

2. Change to an actor pool or router on the fly according to load

3. Implement graceful degradation

4. ...

Page 44: Build Cloud Applications with Akka and Heroku

Quick Note: Akka Futures

• Not the main gist of this talk, but Akka 2.0 includes an incredibly useful Future

class. In Scala 2.10 / Akka 2.1, this class moves to the Scala standard library.

• Unlike Java Future, Akka Future is nonblocking: it has a callback/listener

model.

• Akka includes utilities for converting Future to a message to an actor and

vice-versa.

• Check out http://doc.akka.io/docs/akka/2.0.1/scala/futures.html and

http://doc.akka.io/docs/akka/2.0.1/java/futures.html

Page 45: Build Cloud Applications with Akka and Heroku

Some Akka Best Practices

Page 46: Build Cloud Applications with Akka and Heroku

Create Lots of Actors

Actors are not heavy like threads, they are tiny like objects

Create an actor for every request? No problem

Create a transient actor inline just to handle a single message?

Go for it

Actor tree should be deep, not shallow

Page 47: Build Cloud Applications with Akka and Heroku

Actors Do Only One Thing

Single responsibility principle

Keeps code clear

Lets you add supervision / routing / distribution to any single

thing

Eases debugging

Page 48: Build Cloud Applications with Akka and Heroku

Supervision

Each non-leaf node will be supervising its children

Only supervise one type of child (create intermediate actors to

group children by type)

Don't mix supervision with other actor tasks

Page 49: Build Cloud Applications with Akka and Heroku

No Blocking!

It ties up a thread and causes MASSIVE WASTE of system

resources

If you must block to use some API, give the blocking code a

separate thread pool and isolate it behind an Actor or Future

Page 50: Build Cloud Applications with Akka and Heroku

Name Your Actors

If nothing else, anonymous actors means inscrutable logs

Actors can be referred to by name

Page 51: Build Cloud Applications with Akka and Heroku

Akka on Heroku

Page 52: Build Cloud Applications with Akka and Heroku

How Heroku Works

(super-short version)

You tell it how to start a process (in this case the Java Virtual

Machine)

It automatically runs N copies of the process, one per virtual Linux

instance (the Linux instances are called Dynos)

When the process crashes, automatically creates a new dyno

Apps must be web apps (must listen on HTTP port) though they

can have background jobs

No way to listen on other ports

Services such as databases are available but don't run on dynos...

they are services available to the dynos

Page 53: Build Cloud Applications with Akka and Heroku

Some Akka/Heroku Similarities

Design for scale out

“Let it crash” (just restart the Dyno or the Actor)

Ease of use

Page 55: Build Cloud Applications with Akka and Heroku

Demo

Let's see Akka on Heroku in action.

Page 56: Build Cloud Applications with Akka and Heroku

One Important Caveat

• Remoting/Clustering doesn't work on dynos, because they can only listen on

HTTP.

• i.e. you need to use Heroku clustering, not Akka clustering.

• You can communicate among nodes using many data store and message

queue services available as Heroku add-ons.

– RabbitMQ

– MongoDB

– ...

Page 57: Build Cloud Applications with Akka and Heroku

Some Recap

• Akka is an implementation of the Actor model for both Java and Scala.

• Actors encapsulate mutable state with the guarantee of one message at a time.

• Actor instances don't need to do any locking or think about threads, eliminating a whole

class of bugs and mental overhead.

• The magic comes from the dispatcher, which (by default) combines an event-driven loop

with a thread pool for scalability.

• A single JVM can host millions of actors – far more actors than threads.

• Akka actor jar is small, no dependencies, easy to embed

• Akka comes with a complete toolkit for distributed, fault-tolerant computing, built on actors

as a base.

Page 58: Build Cloud Applications with Akka and Heroku

Akka in Summary

• A way to structure an application

• Three problems addressed

– Concurrency

– Fault Tolerance

– Distribution / Remoting

• Small, easy-to-embed, no-dependencies library

Page 59: Build Cloud Applications with Akka and Heroku

• Follow us @Typesafe on Twitter, or typesafe.com

• Check out the extensive docs on http://akka.io

• Try writing some Akka code!

Page 60: Build Cloud Applications with Akka and Heroku