Merge pull request #164 from jboner/wip-1169-actor-system-doc-rk
received okay by mail
This commit is contained in:
commit
06a13d3eb1
7 changed files with 380 additions and 38 deletions
114
akka-docs/general/actor-systems.rst
Normal file
114
akka-docs/general/actor-systems.rst
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
.. _actor-systems:
|
||||||
|
|
||||||
|
Actor Systems
|
||||||
|
=============
|
||||||
|
|
||||||
|
Actors are objects which encapsulate state and behavior, they communicate
|
||||||
|
exclusively by exchanging messages which are placed into the recipient’s
|
||||||
|
mailbox. In a sense, actors are the most strigent form of object-oriented
|
||||||
|
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
|
||||||
|
the software implementation.
|
||||||
|
|
||||||
|
Hierarchical Structure
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
supervisor, which is the actor which created it.
|
||||||
|
|
||||||
|
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
|
||||||
|
should react nominally and how failure should be handled. If one actor does not
|
||||||
|
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
|
||||||
|
trying to keep everything “under the carpet”.
|
||||||
|
|
||||||
|
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
|
||||||
|
guide lines which might be helpful:
|
||||||
|
|
||||||
|
- 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
|
||||||
|
them.
|
||||||
|
|
||||||
|
- 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
|
||||||
|
Erlang.
|
||||||
|
|
||||||
|
- 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 supervision strategy, and it should be noted that a
|
||||||
|
functional dependency alone is not a criterion for deciding where to place a
|
||||||
|
certain child actor in the hierarchy.
|
||||||
|
|
||||||
|
There are of course always exceptions to these rules, but no matter whether you
|
||||||
|
follow the rules or break them, you should always have a reason.
|
||||||
|
|
||||||
|
Configuration Container
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
used as building blocks in a functional hierarchy.
|
||||||
|
|
||||||
|
Actor Best Practices
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
#. 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
|
||||||
|
them.
|
||||||
|
|
||||||
|
#. Do not pass between actors mutable objects which you actually mutate. 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.
|
||||||
|
|
||||||
|
#. 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
|
||||||
|
experience.
|
||||||
|
|
||||||
|
What you should not concern yourself with
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
while Akka does the heavy lifting under the hood.
|
||||||
|
|
||||||
142
akka-docs/general/actors.rst
Normal file
142
akka-docs/general/actors.rst
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
.. _actors-general:
|
||||||
|
|
||||||
|
What is an Actor?
|
||||||
|
=================
|
||||||
|
|
||||||
|
The previous section about :ref:`actor-systems` explained how actors form
|
||||||
|
hierarchies and are the smallest unit when building an application. This
|
||||||
|
section looks at one such actor in isolation, explaining the concepts you
|
||||||
|
encounter while implementing it. For more an in depth reference with all the
|
||||||
|
details please refer to :ref:`actors-scala` and :ref:`untyped-actors-java`.
|
||||||
|
|
||||||
|
An actor is a container for `State`_, `Behavior`_, a `Mailbox`_, `Children`_
|
||||||
|
and a `Fault Handling Strategy`_. All of this is encapsulated behind an `Actor
|
||||||
|
Reference`_. Finally, this happens `When and Actor Terminates`_.
|
||||||
|
|
||||||
|
Actor Reference
|
||||||
|
---------------
|
||||||
|
|
||||||
|
As detailed below, an actor object needs to be shielded from the outside in
|
||||||
|
order to benefit from the actor model. Therefore, actors are represented to the
|
||||||
|
outside using actor references, which are objects that can be passed around
|
||||||
|
freely and without restriction. This split into inner and outer object enables
|
||||||
|
transparency for all the desired operations: restarting an actor without
|
||||||
|
needing to update references elsewhere, placing the actual actor object on
|
||||||
|
remote hosts, sending messages to actors in completely different applications.
|
||||||
|
But the most important aspect is that it is not possible to look inside an
|
||||||
|
actor and get hold of its state from the outside, unless the actor unwisely
|
||||||
|
publishes this information itself.
|
||||||
|
|
||||||
|
State
|
||||||
|
-----
|
||||||
|
|
||||||
|
Actor objects will typically contain some variables which reflect possible
|
||||||
|
states the actor may be in. This can be an explicit state machine (e.g. using
|
||||||
|
the :ref:`fsm` module), or it could be a counter, set of listeners, pending
|
||||||
|
requests, etc. These data are what make an actor valuable, and they must be
|
||||||
|
protected from corruption by other actors. The good news is that Akka actors
|
||||||
|
conceptually each have their own light-weight thread, which is completely
|
||||||
|
shielded from the rest of the system. This means that instead of having to
|
||||||
|
synchronize access using locks you can just write your actor code without
|
||||||
|
worrying about concurrency at all.
|
||||||
|
|
||||||
|
Behind the scenes Akka will run sets of actors on sets of real threads, where
|
||||||
|
typically many actors share one thread, and subsequent invocations of one actor
|
||||||
|
may end up being processed on different threads. Akka ensures that this
|
||||||
|
implementation detail does not affect the single-threadedness of handling the
|
||||||
|
actor’s state.
|
||||||
|
|
||||||
|
Because the internal state is vital to an actor’s operations, having
|
||||||
|
inconsistent state is fatal. Thus, when the actor fails and is restarted by its
|
||||||
|
supervisor, the state will be created from scratch, like upon first creating
|
||||||
|
the actor. This is to enable the ability of self-healing of the system.
|
||||||
|
|
||||||
|
Behavior
|
||||||
|
--------
|
||||||
|
|
||||||
|
Every time a message is processed, it is matched against the current behavior
|
||||||
|
of the actor. Behavior means a function which defines the actions to be taken
|
||||||
|
in reaction to the message at that point in time, say forward a request if the
|
||||||
|
client is authorized, deny it otherwise. This behavior may change over time,
|
||||||
|
e.g. because different clients obtain authorization over time, or because the
|
||||||
|
actor may go into an “out-of-service” mode and later come back. These changes
|
||||||
|
are achieved by either encoding them in state variables which are read from the
|
||||||
|
behavior logic, or the function itself may be swapped out at runtime, see the
|
||||||
|
``become`` and ``unbecome`` operations. However, the initial behavior defined
|
||||||
|
during construction of the actor object is special in the sense that a restart
|
||||||
|
of the actor will reset its behavior to this initial one.
|
||||||
|
|
||||||
|
Mailbox
|
||||||
|
-------
|
||||||
|
|
||||||
|
An actor’s purpose is the processing of messages, and these messages were sent
|
||||||
|
to the actor from other actors (or from outside the actor system). The piece
|
||||||
|
which connects sender and receiver is the actor’s mailbox: each actor has
|
||||||
|
exactly one mailbox to which all senders enqueue their messages. Enqueuing
|
||||||
|
happens in the time-order of send operations, which means that messages sent
|
||||||
|
from different actors may not have a defined order at runtime due to the
|
||||||
|
apparent randomness of distributing actors across threads. Sending multiple
|
||||||
|
messages to the same target from the same actor, on the other hand, will
|
||||||
|
enqueue them in the same order.
|
||||||
|
|
||||||
|
There are different mailbox implementations to choose from, the default being a
|
||||||
|
FIFO: the order of the messages processed by the actor matches the order in
|
||||||
|
which they were enqueued. This is usually a good default, but applications may
|
||||||
|
need to prioritize some messages over others. In this case, a priority mailbox
|
||||||
|
will enqueue not always at the end but at a position as given by the message
|
||||||
|
priority, which might even be at the front. While using such a queue, the order
|
||||||
|
of messages processed will naturally be defined by the queue’s algorithm and in
|
||||||
|
general not be FIFO.
|
||||||
|
|
||||||
|
An important feature in which Akka differs from some other actor model
|
||||||
|
implementations is that the current behavior must always handle the next
|
||||||
|
dequeued message, there is no scanning the mailbox for the next matching one.
|
||||||
|
Failure to handle a message will typically be treated as a failure, unless this
|
||||||
|
behavior is overridden.
|
||||||
|
|
||||||
|
Children
|
||||||
|
--------
|
||||||
|
|
||||||
|
Each actor is potentially a supervisor: if it creates children for delegating
|
||||||
|
sub-tasks, it will automatically supervise them. The list of children is
|
||||||
|
maintained within the actor’s context and the actor has access to it.
|
||||||
|
Modifications to the list are done by creating (``context.actorOf(...)``) or
|
||||||
|
stopping (``context.stop(child)``) children and these actions are reflected
|
||||||
|
immediately. The actual creation and termination actions happen behind the
|
||||||
|
scenes in an asynchronous way, so they do not “block” their supervisor.
|
||||||
|
|
||||||
|
Fault Handling Strategy
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
The final piece of an actor is its strategy for handling faults of its
|
||||||
|
children. To keep it simple and robust, this is declared outside of the actor’s
|
||||||
|
code and has no access to the actor’s state. Fault handling is then done
|
||||||
|
transparently by Akka, applying one of the strategies described in
|
||||||
|
:ref:`supervision` for each incoming failure. As this strategy is fundamental
|
||||||
|
to how an actor system is structured, it cannot be changed once an actor has
|
||||||
|
been created.
|
||||||
|
|
||||||
|
Considering that there is only one such strategy for each actor, this means
|
||||||
|
that if different strategies apply to the various children of an actor, the
|
||||||
|
children should be grouped beneath intermediate supervisors with matching
|
||||||
|
strategies, preferring once more the structuring of actor systems according to
|
||||||
|
the splitting of tasks into sub-tasks.
|
||||||
|
|
||||||
|
When an Actor Terminates
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Once an actor terminates, i.e. fails in a way which is not handled by a
|
||||||
|
restart, stops itself or is stopped by its supervisor, it will free up its
|
||||||
|
resources, draining all remaining messages from its mailbox into the system’s
|
||||||
|
“dead letter mailbox”. The mailbox is then replaced within the actor reference
|
||||||
|
with a that system mailbox, redirecting all new messages “into the drain”. This
|
||||||
|
is done on a best effort basis, though, so do not rely on it in order to
|
||||||
|
construct “guaranteed delivery”.
|
||||||
|
|
||||||
|
The reason for not just silently dumping the messages was inspired by our
|
||||||
|
tests: we register the TestEventListener on the event bus to which the dead
|
||||||
|
letters are forwarded, and that will log a warning for every dead letter
|
||||||
|
received—this has been very helpful for deciphering test failures more quickly.
|
||||||
|
It is conceivable that this feature may also be of use for other purposes.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,9 +2,10 @@ Actor References, Paths and Addresses
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
This chapter describes how actors are identified and located within a possibly
|
This chapter describes how actors are identified and located within a possibly
|
||||||
distributed actor system. It ties into the central idea that actor systems form
|
distributed actor system. It ties into the central idea that
|
||||||
intrinsic supervision hierarchies as well as that communication between actors
|
:ref:`actor-systems` form intrinsic supervision hierarchies as well as that
|
||||||
is transparent with respect to their placement across multiple network nodes.
|
communication between actors is transparent with respect to their placement
|
||||||
|
across multiple network nodes.
|
||||||
|
|
||||||
What is an Actor Reference?
|
What is an Actor Reference?
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
@ -84,7 +85,7 @@ actors in the hierarchy from the root up. Examples are::
|
||||||
Here, ``akka`` is the default remote protocol for the 2.0 release, and others
|
Here, ``akka`` is the default remote protocol for the 2.0 release, and others
|
||||||
are pluggable. The interpretation of the host & port part (i.e.
|
are pluggable. The interpretation of the host & port part (i.e.
|
||||||
``serv.example.com:5678`` in the example) depends on the transport mechanism
|
``serv.example.com:5678`` in the example) depends on the transport mechanism
|
||||||
used, but it should abide by the URI structural rules.
|
used, but it must abide by the URI structural rules.
|
||||||
|
|
||||||
Logical Actor Paths
|
Logical Actor Paths
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -144,7 +145,7 @@ Creating Actors
|
||||||
An actor system is typically started by creating actors above the guardian
|
An actor system is typically started by creating actors above the guardian
|
||||||
actor using the :meth:`ActorSystem.actorOf` method and then using
|
actor using the :meth:`ActorSystem.actorOf` method and then using
|
||||||
:meth:`ActorContext.actorOf` from within the created actors to spawn the actor
|
:meth:`ActorContext.actorOf` from within the created actors to spawn the actor
|
||||||
tree. These methods return a reference to the newly created actors. Each actor
|
tree. These methods return a reference to the newly created actor. Each actor
|
||||||
has direct access to references for its parent, itself and its children. These
|
has direct access to references for its parent, itself and its children. These
|
||||||
references may be sent within messages to other actors, enabling those to reply
|
references may be sent within messages to other actors, enabling those to reply
|
||||||
directly.
|
directly.
|
||||||
|
|
@ -152,17 +153,17 @@ directly.
|
||||||
Looking up Actors by Concrete Path
|
Looking up Actors by Concrete Path
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
In addition, actor references may be looked up using the
|
In addition, actor references may be looked up using the
|
||||||
:meth:`ActorSystem.actorFor` method, which returns an (unverified) local,
|
:meth:`ActorSystem.actorFor` method, which returns an (unverified) local,
|
||||||
remote or clustered actor reference. Sending messages to such a reference or
|
remote or clustered actor reference. Sending messages to such a reference or
|
||||||
attempting to observe its livelyhood will traverse the actor hierarchy of the
|
attempting to observe its livelyhood will traverse the actor hierarchy of the
|
||||||
actor system from top to bottom by passing messages from parent to child until
|
actor system from top to bottom by passing messages from parent to child until
|
||||||
either the target is reached or failure is certain, i.e. a name in the path
|
either the target is reached or failure is certain, i.e. a name in the path
|
||||||
does not exist (in practice this process will be optimized using caches, but it
|
does not exist (in practice this process will be optimized using caches, but it
|
||||||
still has added cost compared to using the physical actor path, can for example
|
still has added cost compared to using the physical actor path, which can for
|
||||||
to obtained from the sender reference included in replies from that actor). The
|
example to obtained from the sender reference included in replies from that
|
||||||
messages passed are handled automatically by Akka, so this process is not
|
actor). The messages passed are handled automatically by Akka, so this process
|
||||||
visible to client code.
|
is not visible to client code.
|
||||||
|
|
||||||
Absolute vs. Relative Paths
|
Absolute vs. Relative Paths
|
||||||
```````````````````````````
|
```````````````````````````
|
||||||
|
|
@ -177,12 +178,20 @@ example send a message to a specific sibling::
|
||||||
|
|
||||||
context.actorFor("../brother") ! msg
|
context.actorFor("../brother") ! msg
|
||||||
|
|
||||||
|
Absolute paths may of course also be looked up on `context` in the usual way, i.e.
|
||||||
|
|
||||||
|
.. code-block:: scala
|
||||||
|
|
||||||
|
context.actorFor("/user/serviceA") ! msg
|
||||||
|
|
||||||
|
will work as expected.
|
||||||
|
|
||||||
Querying the Logical Actor Hierarchy
|
Querying the Logical Actor Hierarchy
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Since the actor system forms a file-system like hierarchy, matching on paths is
|
Since the actor system forms a file-system like hierarchy, matching on paths is
|
||||||
possible in the same was as supported by Unix shells: you may replace (parts
|
possible in the same was as supported by Unix shells: you may replace (parts
|
||||||
of) path element names with wildcards (`"*"` and `"?"`) to formulate a
|
of) path element names with wildcards (`«*»` and `«?»`) to formulate a
|
||||||
selection which may match zero or more actual actors. Because the result is not
|
selection which may match zero or more actual actors. Because the result is not
|
||||||
a single actor reference, it has a different type :class:`ActorSelection` and
|
a single actor reference, it has a different type :class:`ActorSelection` and
|
||||||
does not support the full set of operations an :class:`ActorRef` does.
|
does not support the full set of operations an :class:`ActorRef` does.
|
||||||
|
|
@ -261,8 +270,13 @@ other actors are found. The next level consists of the following:
|
||||||
those which are used in the implementation of :meth:`ActorRef.ask`.
|
those which are used in the implementation of :meth:`ActorRef.ask`.
|
||||||
- ``"/remote"`` is an artificial path below which all actors reside whose
|
- ``"/remote"`` is an artificial path below which all actors reside whose
|
||||||
supervisors are remote actor references
|
supervisors are remote actor references
|
||||||
|
|
||||||
|
Future extensions:
|
||||||
|
|
||||||
- ``"/service"`` is an artificial path below which actors can be presented by
|
- ``"/service"`` is an artificial path below which actors can be presented by
|
||||||
means of configuration, i.e. deployed at system start-up or just-in-time
|
means of configuration, i.e. deployed at system start-up or just-in-time
|
||||||
(triggered by look-up) or “mounting” other actors by path—local or remote—to
|
(triggered by look-up)
|
||||||
give them logical names.
|
- ``"/alias"`` is an artificial path below which other actors may be “mounted”
|
||||||
|
(as in the Unix file-system sense) by path—local or remote—to give them
|
||||||
|
logical names.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,11 @@ General
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
actor-systems
|
||||||
|
actors
|
||||||
|
supervision
|
||||||
|
addressing
|
||||||
|
remoting
|
||||||
jmm
|
jmm
|
||||||
message-send-semantics
|
message-send-semantics
|
||||||
configuration
|
configuration
|
||||||
addressing
|
|
||||||
supervision
|
|
||||||
|
|
|
||||||
64
akka-docs/general/remoting.rst
Normal file
64
akka-docs/general/remoting.rst
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
.. _remoting:
|
||||||
|
|
||||||
|
Transparent Remoting
|
||||||
|
====================
|
||||||
|
|
||||||
|
The previous section describes how actor paths are used to make possible
|
||||||
|
transparent remoting. This special feature deserves some extra explanation,
|
||||||
|
because it is a term which was used quite differently in the context of
|
||||||
|
programming languages, platforms and technologies.
|
||||||
|
|
||||||
|
Distributed by Default
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Everything in Akka is designed to work in a distributed setting: all
|
||||||
|
interactions of actors use purely message passing and everything is
|
||||||
|
asynchronous. This effort has been undertaken to ensure that all functions are
|
||||||
|
available equally when running within a single JVM or on a cluster of hundreds
|
||||||
|
of machines. The key for enabling this is to go from remote to local by way of
|
||||||
|
optimization instead of trying to go from local to remote by way of
|
||||||
|
generalization. See `this classic paper
|
||||||
|
<http://labs.oracle.com/techrep/1994/abstract-29.html>`_ for a detailed
|
||||||
|
discussion on why the second approach is bound to fail.
|
||||||
|
|
||||||
|
Ways in which Transparency is Broken
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
What is true of Akka need not be true of the application which uses it, since
|
||||||
|
designing for distributed execution poses some restrictions on what is
|
||||||
|
possible. The most obvious one is that all messages sent over the wire must be
|
||||||
|
serializable. While being a little less obvious this includes closures which
|
||||||
|
are used as actor factories (i.e. within :class:`Props`) if the actor is to be
|
||||||
|
created on a remote node.
|
||||||
|
|
||||||
|
Another consequence is that everything needs to be aware of all interactions
|
||||||
|
being fully asynchronous, which in a computer network might mean that it may
|
||||||
|
take several minutes for a message to reach its recipient (depending on
|
||||||
|
configuration). It also means that the probability for a message to be lost is
|
||||||
|
much higher than within one JVM, where it is close to zero (still: no hard
|
||||||
|
guarantee!).
|
||||||
|
|
||||||
|
How is Remoting Used?
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
We took the idea of transparency to the limit in that there is no API for the
|
||||||
|
remoting layer of Akka: it is purely driven by configuration. Just write your
|
||||||
|
application according to the principles outlined in the previous sections, then
|
||||||
|
specify remote deployment of actor sub-trees in the configuration file. This
|
||||||
|
way, your application can be scaled out without having to touch the code.
|
||||||
|
|
||||||
|
Marking Points for Scaling Up with Routers
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
In addition to being able to run different parts of an actor system on
|
||||||
|
different nodes of a cluster, it is also possible to scale up onto more cores
|
||||||
|
by multiplying actor sub-trees which support parallelization (think for example
|
||||||
|
a search engine processing different queries in parallel). The clones can then
|
||||||
|
be routed to in different fashions, e.g. round-robin. The only thing necessary
|
||||||
|
to achieve this is that the developer needs to declare a certain actor as
|
||||||
|
“withRouter”, the in its stead a router actor will be created which will spawn
|
||||||
|
up a configurable number of children of the desired type and route to them in
|
||||||
|
the configured fashion. Once such a router has been declared, its configuration
|
||||||
|
can be freely overridden from the configuration file, including mixing it with
|
||||||
|
the transparent remote deployment of (some of) the children. Read more about
|
||||||
|
this in :ref:`routing`.
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
Supervision
|
.. _supervision:
|
||||||
===========
|
|
||||||
|
Supervision and Monitoring
|
||||||
|
==========================
|
||||||
|
|
||||||
This chapter outlines the concept behind supervision, the primitives offered
|
This chapter outlines the concept behind supervision, the primitives offered
|
||||||
and their semantics. For details on how that translates into real code, please
|
and their semantics. For details on how that translates into real code, please
|
||||||
|
|
@ -8,12 +10,13 @@ refer to the corresponding chapters for Scala and Java APIs.
|
||||||
What Supervision Means
|
What Supervision Means
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Supervision describes a dependency relationship between actors: the supervisor
|
As described in :ref:`actor-systems` supervision describes a dependency
|
||||||
delegates tasks to subordinates and therefore must respond to their failures.
|
relationship between actors: the supervisor delegates tasks to subordinates and
|
||||||
When a subordinate detects a failure (i.e. throws an exception), it suspends
|
therefore must respond to their failures. When a subordinate detects a failure
|
||||||
itself and all its subordinates and sends a message to its supervisor,
|
(i.e. throws an exception), it suspends itself and all its subordinates and
|
||||||
signaling failure. Depending on the nature of the work to be supervised and
|
sends a message to its supervisor, signaling failure. Depending on the nature
|
||||||
the nature of the failure, the supervisor has four basic choices:
|
of the work to be supervised and the nature of the failure, the supervisor has
|
||||||
|
four basic choices:
|
||||||
|
|
||||||
#. Resume the subordinate, keeping its accumulated internal state
|
#. Resume the subordinate, keeping its accumulated internal state
|
||||||
#. Restart the subordinate, clearing out its accumulated internal state
|
#. Restart the subordinate, clearing out its accumulated internal state
|
||||||
|
|
@ -27,7 +30,8 @@ three: resuming an actor resumes all its subordinates, restarting an actor
|
||||||
entails restarting all its subordinates, similarly stopping an actor will also
|
entails restarting all its subordinates, similarly stopping an actor will also
|
||||||
stop all its subordinates. It should be noted that the default behavior of an
|
stop all its subordinates. It should be noted that the default behavior of an
|
||||||
actor is to stop all its children before restarting, but this can be overridden
|
actor is to stop all its children before restarting, but this can be overridden
|
||||||
using the :meth:`preRestart` hook.
|
using the :meth:`preRestart` hook; the recursive restart applies to all
|
||||||
|
children left after this hook has been executed.
|
||||||
|
|
||||||
Each supervisor is configured with a function translating all possible failure
|
Each supervisor is configured with a function translating all possible failure
|
||||||
causes (i.e. exceptions) into one of the four choices given above; notably,
|
causes (i.e. exceptions) into one of the four choices given above; notably,
|
||||||
|
|
@ -46,7 +50,7 @@ makes the formation of actor supervision hierarchies explicit and encourages
|
||||||
sound design decisions. It should be noted that this also guarantees that
|
sound design decisions. It should be noted that this also guarantees that
|
||||||
actors cannot be orphaned or attached to supervisors from the outside, which
|
actors cannot be orphaned or attached to supervisors from the outside, which
|
||||||
might otherwise catch them unawares. In addition, this yields a natural and
|
might otherwise catch them unawares. In addition, this yields a natural and
|
||||||
clean shutdown procedure for (parts of) actor applications.
|
clean shutdown procedure for (sub-trees of) actor applications.
|
||||||
|
|
||||||
What Restarting Means
|
What Restarting Means
|
||||||
---------------------
|
---------------------
|
||||||
|
|
@ -90,12 +94,11 @@ it may react to the other actor’s termination, in contrast to supervision whic
|
||||||
reacts to failure.
|
reacts to failure.
|
||||||
|
|
||||||
Lifecycle monitoring is implemented using a :class:`Terminated` message to be
|
Lifecycle monitoring is implemented using a :class:`Terminated` message to be
|
||||||
received by the behavior of the monitoring actor, where the default behavior is
|
received by the monitoring actor, where the default behavior is to throw a
|
||||||
to throw a special :class:`DeathPactException` if not otherwise handled. One
|
special :class:`DeathPactException` if not otherwise handled. One important
|
||||||
important property is that the message will be delivered irrespective of the
|
property is that the message will be delivered irrespective of the order in
|
||||||
order in which the monitoring request and target’s termination occur, i.e. you
|
which the monitoring request and target’s termination occur, i.e. you still get
|
||||||
still get the message even if at the time of registration the target is already
|
the message even if at the time of registration the target is already dead.
|
||||||
dead.
|
|
||||||
|
|
||||||
Monitoring is particularly useful if a supervisor cannot simply restart its
|
Monitoring is particularly useful if a supervisor cannot simply restart its
|
||||||
children and has to stop them, e.g. in case of errors during actor
|
children and has to stop them, e.g. in case of errors during actor
|
||||||
|
|
@ -104,6 +107,6 @@ them or schedule itself to retry this at a later time.
|
||||||
|
|
||||||
Another common use case is that an actor needs to fail in the absence of an
|
Another common use case is that an actor needs to fail in the absence of an
|
||||||
external resource, which may also be one of its own children. If a third party
|
external resource, which may also be one of its own children. If a third party
|
||||||
terminates a child by way of the ``stop()`` method or sending a
|
terminates a child by way of the ``system.stop(child)`` method or sending a
|
||||||
:class:`PoisonPill`, the supervisor might well be affected.
|
:class:`PoisonPill`, the supervisor might well be affected.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _fsm:
|
||||||
|
|
||||||
###
|
###
|
||||||
FSM
|
FSM
|
||||||
###
|
###
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue