Akka – Really mountains of Concurrency


Akka – Concurrent & Fault-tolerant framework

Now-a-days, concurrent, fault-tolerant, and scalability mechanism is required in most of the application. In most of the time we use concurrent utils in Java for achieving concurrency. But it is very hard to implement it in the abstract level. We need to manage thread – locking, to avoid race-conditions, synchronizations. I found Akka framework, I would say, it is a very thin layer for concurrent process to implement for our applications. Akka – everything is “Actor” model that forms a hierarchy for its child actors and also it does the supervisions of their child.

How Fault-tolerant can accomplish in Akka, the supervision and return back notification to its parent is the way to do. Actor is the light weight process to do the task in parallel as well as in distributed manner.

By the way, from Akka about Actors,

Actors give you:

• Simple and high-level abstractions for concurrency and parallelism.
• Asynchronous, non-blocking and highly performant event-driven programming model.
• Very lightweight event-driven processes (approximately 2.7 million actors per GB RAM).

Akka flow – Example 1

Akka flow – Example 2

Image Courtesy – http://typesafe.com/

Actor System

Actor System is the one, which will be the top node in the tree. There is a best practice to keep a one Actor System per application. Since, it is heavy weight and also it has the responsibility to do the initial setup of configuration in your actor model. The actor system as a collaborating ensemble of actors is the natural unit for managing shared facilities like scheduling services, configuration, logging, etc. An actor is a container for State, Behavior, a Mailbox, Children and a Supervisor Strategy. All of this is encapsulated behind an Actor Reference. Finally, this happens When an Actor Terminates.

Durable Mailboxes

Akka supports a set of durable mailboxes. A durable mailbox is a replacement for the standard actor mailbox that is durable. What this means in practice is that if there are pending messages in the actor’s mailbox when the node of the actor resides on crashes, then when you restart the node, the actor will be able to continue processing as if nothing had happened; with all pending messages still in its mailbox.

The durable mailboxes currently supported are:

• FileBasedMailbox – backed by a journaling transaction log on the local file system
• RedisBasedMailbox – backed by Redis
• ZooKeeperBasedMailbox – backed by ZooKeeper
• BeanstalkBasedMailbox – backed by Beanstalkd
• MongoBasedMailbox – backed by MongoDB

We can set the priority order in which to process the messages from the mailbox.

Actor Configurations

In Akka, every actor, we can define its execution process behavior and also can specify the cluster of actors in the configuration by scale out at any point of time without modify the code.

 ServerSys { include "common" akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { transport = "akka.remote.netty.NettyRemoteTransport" netty { hostname = "127.0.0.1" port = 2552 } } } } ClientSys { include "common" akka { actor { provider = "akka.remote.RemoteActorRefProvider" deployment { /remoteServerActor { remote = "akka://ServerSys@127.0.0.1:2552" } } } } } 

For cluster configuration, it is similar to DHT model used in Cassandra. We can add / remove seeds at any time.

 akka { cluster { # Initial contact points of the cluster. Nodes to join at startup if auto-join = on. # Comma separated full URIs defined by a string on the form of # "akka://system@hostname:port" # Leave as empty if the node should be a singleton cluster. seed-nodes = [] # how long to wait for one of the seed nodes to reply to initial join request seed-node-timeout = 5s # Automatic join the seed-nodes at startup. # If seed-nodes is empty it will join itself and become a single node cluster. auto-join = on # Should the 'leader' in the cluster be allowed to automatically mark unreachable # nodes as DOWN? # Using auto-down implies that two separate clusters will automatically be formed # in case of network partition. auto-down = off …. } } 

Message Dispatchers

This is the heart of the system; it does the Inter actor communication. Every ActorSystem will have a default dispatcher that will be used in case nothing else is configured for an Actor. The default dispatcher can be configured, and is by default a Dispatcher with a “fork-join-executor”, which gives excellent performance in most cases.

There are four types of message dispatchers;

Dispatcher

This is an event-based dispatcher that binds a set of Actors to a thread pool. It is the default dispatcher used if one is not specified.

PinnedDispatcher

This dispatcher dedicates a unique thread for each actor using it; i.e. each actor will have its own thread pool with only one thread in the pool.

BalancingDispatcher

This is an executor based event driven dispatcher that will try to redistribute work from busy actors to idle actors. This will assume that all the actors are in the same pool.

CallingThreadDispatcher

This dispatcher runs invocations on the current thread only. This dispatcher does not create any new threads, but it can be used from different threads concurrently for the same actor.

Software Transactional Memory

This will keeps the transactional data set in the memory for begin/commit/rollback semantics. This is very useful, when a child actor fails, the parent can rollback the transaction.

By Experimental Use-Cases:

Transaction processing (online gaming, finance, statistics, social media, telecom, …), Service backend (any industry, any app), Batch processing ( any industry ), Communications hub ( telecom, web media, mobile media ), Game server (online gaming), BI/datamining/general purpose crunching and more similar.

To get more familiar in Akka framework, please try the examples in the github –
https://github.com/write2munish/Akka-Essentials