2011-12-15 12:05:48 +01:00
|
|
|
|
.. _actor-systems:
|
2011-12-14 20:26:28 +01:00
|
|
|
|
|
|
|
|
|
|
Actor Systems
|
|
|
|
|
|
=============
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
Actors are objects which encapsulate state and behavior, they communicate
|
|
|
|
|
|
exclusively by exchanging messages which are placed into the recipient’s
|
2012-02-14 19:50:01 +07:00
|
|
|
|
mailbox. In a sense, actors are the most stringent form of object-oriented
|
2012-01-23 13:49:19 +01:00
|
|
|
|
programming, but it serves better to view them as persons: while modeling a
|
|
|
|
|
|
solution with actors, envision a group of people and assign sub-tasks to them,
|
|
|
|
|
|
arrange their functions into an organizational structure and think about how to
|
|
|
|
|
|
escalate failure (all with the benefit of not actually dealing with people,
|
|
|
|
|
|
which means that we need not concern ourselves with their emotional state or
|
|
|
|
|
|
moral issues). The result can then serve as a mental scaffolding for building
|
2011-12-14 20:26:28 +01:00
|
|
|
|
the software implementation.
|
|
|
|
|
|
|
|
|
|
|
|
Hierarchical Structure
|
|
|
|
|
|
----------------------
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
Like in an economic organization, actors naturally form hierarchies. One actor,
|
|
|
|
|
|
which is to oversee a certain function in the program might want to split up
|
|
|
|
|
|
its task into smaller, more manageable pieces. For this purpose it starts child
|
|
|
|
|
|
actors which it supervises. While the details of supervision are explained
|
|
|
|
|
|
:ref:`here <supervision>`, we shall concentrate on the underlying concepts in
|
|
|
|
|
|
this section. The only prerequisite is to know that each actor has exactly one
|
2011-12-15 17:12:19 +01:00
|
|
|
|
supervisor, which is the actor that created it.
|
2011-12-14 20:26:28 +01:00
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
The quintessential feature of actor systems is that tasks are split up and
|
|
|
|
|
|
delegated until they become small enough to be handled in one piece. In doing
|
|
|
|
|
|
so, not only is the task itself clearly structured, but the resulting actors
|
|
|
|
|
|
can be reasoned about in terms of which messages they should process, how they
|
2012-04-24 07:59:12 +02:00
|
|
|
|
should react normally and how failure should be handled. If one actor does not
|
2012-01-23 13:49:19 +01:00
|
|
|
|
have the means for dealing with a certain situation, it sends a corresponding
|
|
|
|
|
|
failure message to its supervisor, asking for help. The recursive structure
|
|
|
|
|
|
then allows to handle failure at the right level.
|
|
|
|
|
|
|
|
|
|
|
|
Compare this to layered software design which easily devolves into defensive
|
|
|
|
|
|
programming with the aim of not leaking any failure out: if the problem is
|
|
|
|
|
|
communicated to the right person, a better solution can be found than if
|
2011-12-14 20:26:28 +01:00
|
|
|
|
trying to keep everything “under the carpet”.
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
Now, the difficulty in designing such a system is how to decide who should
|
|
|
|
|
|
supervise what. There is of course no single best solution, but there are a few
|
2012-04-24 07:59:12 +02:00
|
|
|
|
guidelines which might be helpful:
|
2011-12-14 20:26:28 +01:00
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
- If one actor manages the work another actor is doing, e.g. by passing on
|
|
|
|
|
|
sub-tasks, then the manager should supervise the child. The reason is that
|
|
|
|
|
|
the manager knows which kind of failures are expected and how to handle
|
2011-12-14 20:26:28 +01:00
|
|
|
|
them.
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
- If one actor carries very important data (i.e. its state shall not be lost
|
|
|
|
|
|
if avoidable), this actor should source out any possibly dangerous sub-tasks
|
|
|
|
|
|
to children it supervises and handle failures of these children as
|
|
|
|
|
|
appropriate. Depending on the nature of the requests, it may be best to
|
|
|
|
|
|
create a new child for each request, which simplifies state management for
|
|
|
|
|
|
collecting the replies. This is known as the “Error Kernel Pattern” from
|
2011-12-14 20:26:28 +01:00
|
|
|
|
Erlang.
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
- If one actor depends on another actor for carrying out its duty, it should
|
|
|
|
|
|
watch that other actor’s liveness and act upon receiving a termination
|
|
|
|
|
|
notice. This is different from supervision, as the watching party has no
|
|
|
|
|
|
influence on the supervisor strategy, and it should be noted that a
|
|
|
|
|
|
functional dependency alone is not a criterion for deciding where to place a
|
2011-12-14 20:26:28 +01:00
|
|
|
|
certain child actor in the hierarchy.
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
There are of course always exceptions to these rules, but no matter whether you
|
2011-12-14 20:26:28 +01:00
|
|
|
|
follow the rules or break them, you should always have a reason.
|
|
|
|
|
|
|
|
|
|
|
|
Configuration Container
|
|
|
|
|
|
-----------------------
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
The actor system as a collaborating ensemble of actors is the natural unit for
|
|
|
|
|
|
managing shared facilities like scheduling services, configuration, logging,
|
|
|
|
|
|
etc. Several actor systems with different configuration may co-exist within the
|
|
|
|
|
|
same JVM without problems, there is no global shared state within Akka itself.
|
|
|
|
|
|
Couple this with the transparent communication between actor systems—within one
|
|
|
|
|
|
node or across a network connection—to see that actor systems themselves can be
|
2011-12-14 20:26:28 +01:00
|
|
|
|
used as building blocks in a functional hierarchy.
|
|
|
|
|
|
|
|
|
|
|
|
Actor Best Practices
|
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
#. Actors should be like nice co-workers: do their job efficiently without
|
|
|
|
|
|
bothering everyone else needlessly and avoid hogging resources. Translated
|
|
|
|
|
|
to programming this means to process events and generate responses (or more
|
|
|
|
|
|
requests) in an event-driven manner. Actors should not block (i.e. passively
|
|
|
|
|
|
wait while occupying a Thread) on some external entity, which might be a
|
|
|
|
|
|
lock, a network socket, etc. The blocking operations should be done in some
|
|
|
|
|
|
special-cased thread which sends messages to the actors which shall act on
|
2011-12-14 20:26:28 +01:00
|
|
|
|
them.
|
|
|
|
|
|
|
2011-12-15 17:12:19 +01:00
|
|
|
|
#. Do not pass mutable objects between actors. In order to ensure that, prefer
|
|
|
|
|
|
immutable messages. If the encapsulation of actors is broken by exposing
|
|
|
|
|
|
their mutable state to the outside, you are back in normal Java concurrency
|
|
|
|
|
|
land with all the drawbacks.
|
2011-12-14 20:26:28 +01:00
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
#. Actors are made to be containers for behavior and state, embracing this
|
|
|
|
|
|
means to not routinely send behavior within messages (which may be tempting
|
|
|
|
|
|
using Scala closures). One of the risks is to accidentally share mutable
|
|
|
|
|
|
state between actors, and this violation of the actor model unfortunately
|
|
|
|
|
|
breaks all the properties which make programming in actors such a nice
|
2011-12-14 20:26:28 +01:00
|
|
|
|
experience.
|
|
|
|
|
|
|
2012-04-23 12:25:33 +02:00
|
|
|
|
#. Top-level actors are the innermost part of your Error Kernel, so create them
|
|
|
|
|
|
sparingly and prefer truly hierarchical systems. This has benefits wrt.
|
|
|
|
|
|
fault-handling (both considering the granularity of configuration and the
|
|
|
|
|
|
performance) and it also reduces the number of blocking calls made, since
|
|
|
|
|
|
the creation of top-level actors involves synchronous messaging.
|
|
|
|
|
|
|
2011-12-14 20:26:28 +01:00
|
|
|
|
What you should not concern yourself with
|
|
|
|
|
|
-----------------------------------------
|
|
|
|
|
|
|
2012-01-23 13:49:19 +01:00
|
|
|
|
An actor system manages the resources it is configured to use in order to run
|
|
|
|
|
|
the actors which it contains. There may be millions of actors within one such
|
|
|
|
|
|
system, after all the mantra is to view them as abundant and they weigh in at
|
|
|
|
|
|
an overhead of only roughly 300 bytes per instance. Naturally, the exact order
|
|
|
|
|
|
in which messages are processed in large systems is not controllable by the
|
|
|
|
|
|
application author, but this is also not intended. Take a step back and relax
|
2011-12-14 20:26:28 +01:00
|
|
|
|
while Akka does the heavy lifting under the hood.
|
|
|
|
|
|
|