Akka Actor System
来源:akka文档
Actors are objects which encapsulate (封装)state and behavior, they communicate exclusively by exchanging messages
which are placed into the recipient’s mailbox.
Note: An ActorSystem is a heavyweight structure that will allocate 1. . . N Threads, so create one per logical
application.
An actor is a container for State, Behavior, a Mailbox, Children and a Supervisor(监督管理) Strategy. All of this is encapsulated(封装) behind an Actor Reference.
actors以树形结构组织起来,类似一个生态系统。例如,一个actor可能会把自己的任务划分成更多更小的、利于管理的子任务。为了这个目的,它会开启自己的子actor,并负责监督这些子actor。关于监督的具体细节就不在这里讨论了。我们只要知道一点,就是每一个actor都会有一个监督者,那就是创建这些actor的那个actor。
如下图:
actor系统的精华就是任务的分解。任务要被分割的要足够小,每个分片都会被委托给子actor。这里用到的思想很明显就是“分而治之”,万变不离其宗啊!要想做好这一切,不仅仅要把任务组织的非常清晰(利于分解),也要对处理任务的最终actor在以下方面进行考虑:哪些消息需要处理、如何正常的回应、如何处理失败等等。如果一个处理特定任务的actor失败了,它会向它的监督者发出响应错误的消息去寻求错误处理的方法。这种递归式(监督者也有自己的监督者)的结构可以保证错误在合适的级别上进行处理。
设计这样一种系统的难点在于如何去确定“谁来监督 ” 和“监督什么"。这两个问题虽然没有最佳解决方案,但是还是有一些有用的指导规则。
如果一个actor管理工作,拎一个actor来执行工作。例如,把子任务发送给工作actor。管理actor需要监督工作actor。因为管理actor知道会出现哪种错误,并且应该如何去处理它们。
如果一个actor持有非常重要的数据(它的状态值尽量不能丢失),它应该把子任务分给自己监督的子actor。这样它就能根据情况来处理这些子actor失败。根据任务请求的性质,最好为每一个任务分配一个新的子actor,这样会简化收集子actor相应时的状态管理。
如果一个actor依赖另一个actor才能完成自己的任务,它应该监控那个actor的活动状态,并且对那个actor的关闭事件做出响应。这个和监督还是不同的,监控的一方对监督策略没有任何影响。
在Akka里面,和Actor通信的唯一方式就是通过ActorRef。ActorRef代表Actor的一个引用,可以阻止其他对象直接访问或操作这个Actor的内部信息和状态。
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.
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 fsm-scala 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.
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.
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.
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.
The final piece of an actor is its strategy for handling faults of its children. Fault handling is then done transparently
by Akka, applying one of the strategies described in Supervision and Monitoring 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.
======================END======================