Applications and systems requirements are constantly evolving. In the past they were monolithic or had only few services running on the same server, they had considerable response times and they needed a certain amount of offline time for maintenance. However, in today’s world systems could be deployed over hundreds or thousands of servers, each of these servers having multiple calls. In addition, users nowadays expect millisecond response times. Akka.NET is a set of open-source libraries for designing Actor Model-based systems that meet today’s specifications: responsiveness, scalability and resilience.
What is an Actor Model?
The Actor model is a conceptual model to deal with concurrent computation. It defines some general rules for how the system’s components should behave and interact with each other. It was described in « A universal modular ACTOR formalism for artificial intelligence » by Carl Hewitt, Peter Bishop and Richard Steiger (1973). But relatively recently, it has been implemented: initial work on Akka dates from 2009 and first version of akka.net was released in 2015.
This computer science concept uses « actors » as the fundamental agents of computing. An « actor » is the fundamental idea in the actor model. It takes input, sends output and performs functions. It can also create other actors.
Actors are stateful entities communicating with each other by explicit message passing. They have these main characteristics:
- Communication with asynchronous messaging
- Management of their own state
- Processing other actions (such as creating other actors or stopping them)
What is a reactive system?
Today’s specifications of systems define reactive systems. Those latter are defined in a document, first released in 2013, The Reactive Manifesto. It defines the core principles of reactive programming. There are 4 core principles:
- Responsiveness (rapid and consistent response times)
- Resilience (system responsive in front of any failure via replication, containment, isolation, and delegation)
- Elasticity (reacting to changes and staying responsive under any workload)
- Message driven system (establishing a boundary between components by relying on asynchronous message passing)
For more info about The Reactive Manifesto: https://www.reactivemanifesto.org/
Akka.NET adheres to the principles set forth in The Reactive Manifesto and is Actor model based.
With Akka.NET we are working with high level of abstractions (actors, messages, etc…) and higher level of concurrency (no manual management of thread nor manual locking of resources). Working with an asynchronous message passing offers simple concurrency since actors are not blocked waiting for responses from other actors. Akka.NET provides a simple remote deployment model where configuration can specify where actors are to be created: it implements the concept of location transparency (c.f. Actor Systems).
Akka.NET is highly performant: it can handle around 50 million messages per second and one gigabyte of heap memory can store around 2.5 million actor instances (average numbers).
Some advanced features Akka.NET offers are load balancing, routing requests to multiple child instances, the possibility to create self-healing systems (through the hierarchies of supervisors).
Actors are a programming paradigm and primitive computational units. It is the place where the work of a system is performed. For a system, a single actor by itself is not enough. This latter is composed of several actors. The actors communicate with each other via messages. The communication between them is optimized. In fact, the passing of messages is asynchronous and no processing is done when no messages is received.
There are four main actions actors can perform:
- Receiving and processing messages
- Creating more actors
- Sending messages to other actors
- Adapting their behaviors for each message
This paradigm takes encapsulation to its extreme. In fact, each actor encapsulates not only its states but also its behavior, i.e. the execution of a small well-defined task implemented in its core. The execution of actors’ code is identical whether they are local or distributed.
Every actor has:
- An incoming message mailbox: messages received are queued for processing
- A behavior: the actor performs a defined action according to the type of message received
- A state: the current state of the actor
- Children E[0…n]
- A possible supervisory strategy: handling faults in children
An actor processes one message at a time. The message is received, stored in the mailbox and processed when the actor is released or wakes up. The actor will continue processing till the mailbox is empty then it sleeps again.
Within the Actor model “everything is an actor”.
In Akka.Net, messages are simple POCO (Plain Old CLR Object) classes: they don’t derive from any special base class. They should be immutable. They can afect the state of an actor when processed.The passing of messages is asynchronous.
An actor system is a set of actors. In a system we can have one or several actor systems. The actors within the same actor system communicate via local messages; however, actors in different actor systems communicate via remote messages. The actor systems could run on the same machine of on a distributed system.
Location transparency is the ability to send a message to an actor without needing to know where it is; whether it is in the same actor system instance or in another actor system instance. It makes it easy to use the communication system in Akka.Net.
Actor Supervision Hierarchies
An actor could have children. If it does, it is responsible for supervising its children. Creating children, we create a certain hierarchy. Parent actors supervise child actors which could be themselves parent: we create then a tree of actors. This hierarchy allows system to be fault tolerant and to be able to self-heal. Self-healing is a feature that help notice that a problem has occurred and automatically find a solution without any external intervention. When an error occurs in a child, the parent is notified, and it is the one responsible to fix the problem via several strategies such as restarting the actor. When the parent actor doesn’t know what to do with its child in error it should notify its parent.
Supervision hierarchy allow the system to not only deal with faults but become self-healing.
In Akka.Net, when we are working with actors, we are not working with a direct reference of actors to make them communicate. Akka.Net provides what we call an “actor reference” (ActorRef). This latter is a layer of indirection that helps pass around the actors’ references throughout the actor system. Each actor instance has several special ActorRefs: reference to itself, reference to its parent and references to all of the children it created.
We can obtain actor references when creating Actors (Actorof()) or by looking up existing actors (ActorSelection()).