Concurrency, Scalability & Fault-tolerance 2.0 with Actors & STMby Mario Fuscomario.fusco@gmail.comtwitter: @mariofusco
Which are the biggestchallengesin contemporary software development?
Deal with overloadedsystems
Do concurrencyeffectively
Design, develop and deployapplicationsthat scale well
The native Java concurrency modelBased on:ThreadsSemaphoresSynchronizationLocksThey are sometimes plain evil …… and sometimes a necessary pain …… but always the wrong default
Actors: a different model of concurrencyImplements Message-Passing Concurrency
Share NOTHING
Isolated lightweight processes
Communicates through messages
Asynchronous and non-blocking
Each actor has a mailbox (message queue)
A single thread can managemany (thousands of) actorsPeople are bad at parallel thinkingWith actors is easier to reason about and easier to avoid: Race conditions, Deadlocks, Starvation and Live locks
What is Akka?An actor based concurrency framework
Written in Scala, butalsoworking in Java
Nowrealeasing 1.0 after 2 years of development (currentlyRC4 available)
Better performances and throughput and smallermemoryfootprint (650 bytes) than native scala actors
Open source (Apache2)Untyped Actorspublic class MyUntypedActorextends UntypedActor {   public void onReceive(Object message) throws Exception {        if (message instanceofString) {            String msg = (String)message;System.out.println("Received message: " + msg);        }    }}UntypedActorRef actor = UntypedActor.actorOf(MyUntypedActor.class);actor.start();// --- Do some work here ---actor.stop();
Sending message to UntypedActorsThere are 3 different ways to send a message to an actor:Fire-and-forget ( !  In Scala )actor.sendOneWay(msg);Uses a Future under the hood, blocking the sender Actor until eithera reply is received or the Future times out ( !!  In Scala )Object res1 = actor.sendRequestReply(msg);Object res2 = actor.sendRequestReply(msg, 1000); // timeoutExplicitly returns a Future ( !!!  In Scala )Future future= actor.sendRequestReplyFuture(msg);IMPORTANT: Messages can be any kind of object but have to be immutable. Akkacan’t enforce immutability (yet) so this has to be by convention
Typed Actorspublic class CounterImplextends TypedActorimplements Counter {    private int counter = 0;    public void count() {        counter++;System.out.println(counter);    }    public intgetCountNr() {returncounter;   }}Counter counter= (Counter)TypedActor             .newInstance(Counter.class, CounterImpl.class, 1000);counter.count(); // Fire-and-forgetintcount = counter.getCountNr(); // uses Future under the hood
“Let it crash” fault-tolerance through supervisor hierarchies
You can’t avoid failures: shit happens
What’swrong in trying to preventerrors?Java and other languages and frameworks (not designed with concurrency in mind) signal faults/errors with exceptionsThrowing an exception in concurrent code will just simply blow up the thread that currently executes the code that threw it:There is no way to find out that things went wrong, apart from inspecting the stack traceThere is nothing you can do to recover from the problem and bring back your system to a normal functioning
Fail fast & build self-repairing systems
SupervisedactorsActors provide a clean way of getting error notification and do something about it
Supervised actors also allow you to create sets (hierarchies) of actors where you can be sure that either all are dead or none are dead
That encourages non-defensive programming: don’t try to prevent things from go wrong, because they will. Failures are a natural state in the life-cycle of your app: crash early and let someone else (that sees the whole picture), deal with it
A supervisor is responsible for starting, stopping and monitoring its child processes. It can act with 2 fault handling strategies:One-For-Oneor All-For-One
Declarative supervised actors configurationSupervisor supervisor = new Supervisor(  new SupervisorConfig(    new AllForOneStrategy(          // or OneForOneStrategy       new Class[]{Exception.class}, // Exceptions to handle       3,           // maximum number of restart retries       5000),       // within time in millis    new Supervise[] {  new Supervise(UntypedActor.actorOf(MyActor1.class),    permanent()), // the actor will always be restarted  new Supervise(UntypedActor.actorOf(MyActor2.class),    temporary())  // the actor won’t be shut down normally}));// You can also link and unlink actors from a supervisorsupervisor.link(actor1);supervisor.unlink(actor1);

Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM

  • 1.
    Concurrency, Scalability &Fault-tolerance 2.0 with Actors & STMby Mario Fuscomario.fusco@gmail.comtwitter: @mariofusco
  • 2.
    Which are thebiggestchallengesin contemporary software development?
  • 3.
  • 4.
  • 5.
    Design, develop anddeployapplicationsthat scale well
  • 6.
    The native Javaconcurrency modelBased on:ThreadsSemaphoresSynchronizationLocksThey are sometimes plain evil …… and sometimes a necessary pain …… but always the wrong default
  • 7.
    Actors: a differentmodel of concurrencyImplements Message-Passing Concurrency
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
    Each actor hasa mailbox (message queue)
  • 13.
    A single threadcan managemany (thousands of) actorsPeople are bad at parallel thinkingWith actors is easier to reason about and easier to avoid: Race conditions, Deadlocks, Starvation and Live locks
  • 14.
    What is Akka?Anactor based concurrency framework
  • 15.
    Written in Scala,butalsoworking in Java
  • 16.
    Nowrealeasing 1.0 after2 years of development (currentlyRC4 available)
  • 17.
    Better performances andthroughput and smallermemoryfootprint (650 bytes) than native scala actors
  • 18.
    Open source (Apache2)UntypedActorspublic class MyUntypedActorextends UntypedActor { public void onReceive(Object message) throws Exception { if (message instanceofString) { String msg = (String)message;System.out.println("Received message: " + msg); } }}UntypedActorRef actor = UntypedActor.actorOf(MyUntypedActor.class);actor.start();// --- Do some work here ---actor.stop();
  • 19.
    Sending message toUntypedActorsThere are 3 different ways to send a message to an actor:Fire-and-forget ( ! In Scala )actor.sendOneWay(msg);Uses a Future under the hood, blocking the sender Actor until eithera reply is received or the Future times out ( !! In Scala )Object res1 = actor.sendRequestReply(msg);Object res2 = actor.sendRequestReply(msg, 1000); // timeoutExplicitly returns a Future ( !!! In Scala )Future future= actor.sendRequestReplyFuture(msg);IMPORTANT: Messages can be any kind of object but have to be immutable. Akkacan’t enforce immutability (yet) so this has to be by convention
  • 20.
    Typed Actorspublic classCounterImplextends TypedActorimplements Counter { private int counter = 0; public void count() { counter++;System.out.println(counter); } public intgetCountNr() {returncounter; }}Counter counter= (Counter)TypedActor .newInstance(Counter.class, CounterImpl.class, 1000);counter.count(); // Fire-and-forgetintcount = counter.getCountNr(); // uses Future under the hood
  • 21.
    “Let it crash”fault-tolerance through supervisor hierarchies
  • 22.
    You can’t avoidfailures: shit happens
  • 23.
    What’swrong in tryingto preventerrors?Java and other languages and frameworks (not designed with concurrency in mind) signal faults/errors with exceptionsThrowing an exception in concurrent code will just simply blow up the thread that currently executes the code that threw it:There is no way to find out that things went wrong, apart from inspecting the stack traceThere is nothing you can do to recover from the problem and bring back your system to a normal functioning
  • 24.
    Fail fast &build self-repairing systems
  • 25.
    SupervisedactorsActors provide aclean way of getting error notification and do something about it
  • 26.
    Supervised actors alsoallow you to create sets (hierarchies) of actors where you can be sure that either all are dead or none are dead
  • 27.
    That encourages non-defensiveprogramming: don’t try to prevent things from go wrong, because they will. Failures are a natural state in the life-cycle of your app: crash early and let someone else (that sees the whole picture), deal with it
  • 28.
    A supervisor isresponsible for starting, stopping and monitoring its child processes. It can act with 2 fault handling strategies:One-For-Oneor All-For-One
  • 29.
    Declarative supervised actorsconfigurationSupervisor supervisor = new Supervisor( new SupervisorConfig( new AllForOneStrategy( // or OneForOneStrategy new Class[]{Exception.class}, // Exceptions to handle 3, // maximum number of restart retries 5000), // within time in millis new Supervise[] { new Supervise(UntypedActor.actorOf(MyActor1.class), permanent()), // the actor will always be restarted new Supervise(UntypedActor.actorOf(MyActor2.class), temporary()) // the actor won’t be shut down normally}));// You can also link and unlink actors from a supervisorsupervisor.link(actor1);supervisor.unlink(actor1);
  • 30.
    Remote actorsAkka providesremote actors in a completely transparent way both in regards to sending messages, error handling and supervision
  • 31.
    Uses a veryefficient and scalable I/O implementation built upon JBossNetty and Google Protocol Buffers
  • 32.
    Can be securedwith a cookie authentication mechanism
  • 33.
    Can be bothTypedand Untyped
  • 34.
  • 35.
    server-managed: run onthe machine thatcreateditwhile client can lookup and obtain a proxy
  • 36.
    client managed: makethemrunningon a different machine while the localone just hold a proxy to sendthemmessagesServer-managedClient-managedTypedBean actor = TypedActor.newInstance(Bean.class, BeanImpl.class, timeout); Actors.remote().start("localhost", 9999) .registerTypedActor( “my-service", actor );Bean remoteActor = (Bean)TypedActor .newRemoteInstance(Bean.class, BeanImpl.class, timeout, "192.68.23.69", 9999 );Untypedclass MyActor extends UntypedActor {}Actors.remote() .actorOf(MyActor.class, "192.68.23.69", 9999 );class MyActor extends UntypedActor {}Actors.remote() .start("localhost", 9999) .register(“my-service", actorOf(MyActor.class) );
  • 37.
    Software Transactional MemoryAnSTM turns the Java heap into a transactional data set with begin/commit/rollback semantics. Very much like a regular database. It implements the first three letters in ACID; ACI: Atomic: all or none of the changes made during a transaction get applied
  • 38.
    Consistent: a transactiongets a consistent of reality
  • 39.
    Isolated: changes madeby concurrent execution transactions are not visible to each otherAkka’s STM implements the concept already present in Clojure’s STMThe STM is based on Transactional References (referred to as Refs). Refs: are memory cells, holding an (arbitrary) immutable value
  • 40.
  • 41.
    are managed andenforced by the STM for coordinated changes across many Refs
  • 42.
    are implemented usingthe excellent Multiverse STM (http://multiverse.codehaus.org)Why we need an STM?public class Container { private int value; private final ReadWriteLock lock = new ReentrantReadWriteLock(); public intgetValue() { lock.readLock().lock(); try { return value; } finally { lock.readLock.unlock(); } }   public void setValue(int value) { lock.writeLock().lock(); try { this.value= value; } finally { lock.writeLock.unlock(); } } }What’swrong with it?Ad-hoc and hardlyreusablelogic
  • 43.
  • 44.
    Lockslimitconcurrency and thenthroughputHowdoes Akka STM work?// Create a Ref with an initial value (also possible without)final Ref<Integer> ref = new Ref<Integer>(0);   public int counter() {// A transaction is delimited using an Atomic anonymous inner class return new Atomic<Integer>() { public Integer atomically() { intinc = ref.get() + 1; // Accessing the value of the Refref.set(inc); // Changing the value of the Ref return inc; } }.execute(); }A transaction is automatically retried when it runs into some read or write conflict
  • 45.
    In this casean (exponential) delay isused to preventfurthercontentions
  • 46.
    Thereshouldn’t be side-effectsinside the transaction to avoid to repeatthemTransactional Datastructuresfinal TransactionalMap<String, User> users = new TransactionalMap<String, User>();  // fill users map (in a transaction)new Atomic() { public Object atomically() { users.put("bill", new User("bill")); users.put("mary", new User("mary")); users.put("john", new User("john")); return null; } }.execute();   // access users map (in a transaction)User user = new Atomic<User>() { public User atomically() { return users.get("bill").get(); } }.execute();
  • 47.
  • 48.
    Coordinating Actors withSTMpublic class Counter extends UntypedActor { private Ref<Integer> count = new Ref(0); private void increment() { count.set(count.get() + 1); } public void onReceive(Object incoming) throws Exception { if (incoming instanceof Coordinated) { Coordinated coordinated = (Coordinated) incoming; Object message = coordinated.getMessage(); if (message instanceof Increment) { Increment increment = (Increment) message; if (increment.hasFriend()) {increment.getFriend() .sendOneWay(coordinated.coordinate(new Increment())); }coordinated.atomic(new Atomically() { public void atomically() { increment(); } });}}}}
  • 49.
    Actors + STM= Transactorspublic class Counter extends UntypedTransactor { Ref<Integer> count = new Ref<Integer>(0); @Override public Set<SendTo> coordinate(Object message) { if (message instanceof Increment) { Increment increment = (Increment) message; if (increment.hasFriend()) return include(increment.getFriend(), new Increment()); } return nobody(); } public void atomically(Object message) { if (message instanceof Increment) {count.set(count.get() + 1); } }}
  • 50.
    Other Akka goodiesImplementsAdvanced Message Queuing Protocol (AMPQ) based on the RabbitMQ
  • 51.
  • 52.
    PersistencemodulesupportingmanyNoSQL DB like:Cassandra, MongoDB, Riak, Redis, Terrastore, CouchDB, Voldemort, Hbase
  • 53.
    Integration betweenAkkaSTM andJTA (Java Transaction API)
  • 54.
  • 55.
    Integration with Springallowing to defineTyped Actors as Spring managed bean
  • 56.
    Integration with LiftWeb Framework and Play! FrameworkThanks a lot!Happy Java (or Scala) hingby Mario Fuscomario.fusco@gmail.comtwitter: @mariofusco