AKKA笔记3
What is Akka?
Scalable real-time transaction processing
We believe that writing correct concurrent, fault-tolerant and scalable applications is too hard. Most of the time it's because we are using the wrong tools and the wrong level of abstraction. Akka is here to change that. Using the Actor Model we raise the abstraction level and provide a better platform to build scalable, resilient and responsive applications—see the Reactive Manifesto for more details. For fault-tolerance we adopt the "let it crash" model which the telecom industry has used with great success to build applications that self-heal and systems that never stop. Actors also provide the abstraction for transparent distribution and the basis for truly scalable and fault-tolerant applications.
Akka is Open Source and available under the Apache 2 License.
Download from http://akka.io/downloads.
Please note that all code samples compile, so if you want direct access to the sources, have a look over at the Akka Docs subproject on github: for Java and Scala.
什么是AKKA?
可扩展的实时事务处理
我们相信,编写正确的并发,容错和可扩展的应用程序是太难了。大多数时候是因为我们使用了错误的工具和错误的抽象层次。Akka将改变这些。使用的Actor模型,我们提高了抽象层次,并提供一个更好的平台,以建立可扩展的,弹性和响应的应用程序看到的反应性宣言更多的细节。对于容错能力,我们采用“让它崩溃”的模式,电信行业已经成功地建立应用程序,自愈和系统,永远不会停止。演员还提供了透明的分布和真正的可扩展性和容错应用的基础。
阿卡是Apache 2许可下的开放源代码和可。
从http://akka.io/downloads下载。
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 stringent 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.
ActorSystem
Actor是封装状态和行为的对象,它们通过将被放置在收件人邮箱中的消息进行通信。在一种意义上,Actor是最严格的形式,面向对象的编程,但它可以更好地把它们看作人:在建模与Actor的解决方案,设想一组人,并分配给他们的任务,安排他们的功能到一个组织结构,并考虑如何升级失败(得益于并不是实际人之间的打交道,这意味着我们需要不关心自己的情绪状态或道德问题)。结果可以作为一个心理支架的软件实现。
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 here, 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 that 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 normally 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 guidelines 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 supervisor 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.
层次结构
就像在一个经济组织中,Actor自然形成层次结构。一个Actor,这是监督在程序中的某些功能可能要分裂成更小,更容易管理的任务。为了这个目的,它会建立子对象并监督子对象。唯一的前提是要知道每个Actor都有一个主管,这个主管创造了它。
ActorSystem最典型的特征是将任务分割和下放,直到它们足够小和轻量级的处理。在这样做时,不仅是任务本身的结构清晰,但由此产生的Actor可以推理的信息,他们应该如何处理,他们应该如何反应,以及如何处理失败。如果一个Actor没有处理某个特定情况的手段,它会向它的主管发出一个相应的故障信息,请求帮助。递归结构,然后允许在正确的水平处理故障。
从软件设计层面上,这样的设计更容易实现容错的程序:这会是一个比较好的方案,将问题传达给正确的人,而不是所有的人都趴在地上。
现在,在设计系统的难度是如何决定谁应该监督。当然没有一个最佳的解决方案,但有一些指导原则,这可能是有益的:
如果一个Actor管理另一个Actor的工作,例如,通过分任务,那么父类应该监督子类。原因是父类知道什么样的失败,以及如何处理它们。
如果一个Actor携带非常重要的数据(即它的状态不应该失去),这个Actor应该发起子任务,并适当的监督和处理这些孩子的失败。根据请求的性质,它可能是最好的为每个请求创建一个新的子类,从而简化了收集回复的状态管理。the “Error Kernel Pattern” from Erlang(不知道怎么翻译,又懂得帮我指正啊)
如果一个Actor取决于另一个Actor,应该观察这个Actor的活动和行为以及收到的终止通知。这不等同于监督,因为这对观看者并没有影响,必须指出的是,这并不是唯一的决定子类层次的标准。
当然,这些规则总是有例外的,但是不管你是否遵守规则,还是要打破规则,你都应该有一个理由。
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.—unless it is unavoidable; in the latter case see below.
- 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.
- 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.
- Top-level actors are the innermost part of your Error Kernel, so create them sparingly and prefer truly hierarchical systems. This has benefits with respect to fault-handling (both considering the granularity of configuration and the performance) and it also reduces the strain on the guardian actor, which is a single point of contention if over-used.
Actor最佳实践
Actor应该像好的同事:有效完成工作而没有麻烦任何人,避免占用资源。在事件驱动的方式中,翻译为编程这意味着处理事件并生成响应(或更多请求)。在某些外部实体中,Actor不应该阻止(即被动地等待),而在某些外部实体可能是一个锁、一个网络插座等,除非它是不可避免的;在后者的情况下见。
Actor之间不要传递易变的对象,更喜欢一成不变的消息。如果Actor的封装是并暴露自己的可变状态,这将失去Akka所有的有点,回到普通java程序的状况。
Actor是一个行为和状态的容器,包括不常见的行为通过消息发送行为(这很可能是使用了Scala闭包)。风险之一是,当偶然共享了Actor之间的可变状态,这违反了Actor模型良好的编程经验。(暂时不理解)
(TODO: Top-level.....)
What is an Actor?
The previous section about 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 a more in depth reference with all the details please refer to Actors (Scala) and Untyped Actors (Java).
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.
什么是Actor?
之前介绍了Actor如何形成层次结构,是构建应用程序最小的单位。本节从一个孤立的Actor角度,解释遇到的概念,同时实施。在深度参考了所有的细节,更请参考 Actors (Scala) and Untyped Actors (Java)。
一个Actor是包含状态,行为,一个邮箱,孩子和一个主管策略。所有这一切都是封装在一个的Actor中。最后,当一个演员结束时:通过停止本身或停止其主管的方式停止下来的,他将释放资源,所有剩余的mail将进入系统的 “dead letter mailbox”并将他们转发EventStream 作为 DeadLetters。
What Supervision Means
As described in Actor Systems supervision describes a dependency relationship between actors: the supervisor delegates tasks to subordinates and therefore must respond to their failures. When a subordinate detects a failure (i.e. throws an exception), it suspends itself and all its subordinates and sends a message to its supervisor, signaling failure. Depending on the nature of the work to be supervised and the nature of the failure, the supervisor has a choice of the following four options:
- Resume the subordinate, keeping its accumulated internal state
- Restart the subordinate, clearing out its accumulated internal state
- Stop the subordinate permanently
- Escalate the failure, thereby failing itself
监督手段
在Actor系统的监督描述了一个Actor之间的依赖关系:主管委托给下属的任务,因此必须回应他们的失败。当一个下属的检测到故障(即抛出一个异常),它将本身及其所有下属和发送一个消息给其主管信号故障。根据工作的性质,监督和性质的失败,主管有以下四个选项的选择:
1.恢复下属,保持内在状态
2.重新启动下属,清除其累积的内部状态
3.永久停止
4.升级失败,从而失败
It is important to always view an actor as part of a supervision hierarchy, which explains the existence of the fourth choice (as a supervisor also is subordinate to another supervisor higher up) and has implications on the first three: resuming an actor resumes all its subordinates, restarting an actor entails restarting all its subordinates (but see below for more details), similarly terminating an actor will also terminate all its subordinates. It should be noted that the default behavior of the preRestart hook of the Actor class is to terminate all its children before restarting, but this hook can be overridden; 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 causes (i.e. exceptions) into one of the four choices given above; notably, this function does not take the failed actor’s identity as an input. It is quite easy to come up with examples of structures where this might not seem flexible enough, e.g. wishing for different strategies to be applied to different subordinates. At this point it is vital to understand that supervision is about forming a recursive fault handling structure. If you try to do too much at one level, it will become hard to reason about, hence the recommended way in this case is to add a level of supervision.
Akka implements a specific form called “parental supervision”. Actors can only be created by other actors—where the top-level actor is provided by the library—and each created actor is supervised by its parent. This restriction makes the formation of actor supervision hierarchies implicit and encourages sound design decisions. It should be noted that this also guarantees that actors cannot be orphaned or attached to supervisors from the outside, which might otherwise catch them unawares. In addition, this yields a natural and clean shutdown procedure for (sub-trees of) actor applications.
重要的是要始终认为一个角色的监督层次,这解释了存在的第四个选择(作为一个主管也属于另一个主管),并有影响的第1和3:恢复一个Actor恢复所有下属,重新启动一个演员需要重新启动所有的下属(但见下面的更多细节),同样终止一个Actor也将终止其所有下属。应该指出的是,Actor的prerestart的默认行为是终止所有的孩子重新启动前,但可以重写;递归重启应用后钩已执行的所有留守子类。
每个主管都配置了一个功能,将所有可能的故障原因(即例外)转化为上述四个选择之一,尤其是,这个功能并没有把失败的演员的身份作为输入。这是很容易提出的例子,这可能是不够灵活的结构,如希望不同的策略,以适用于不同的下属。在这一点上,了解这一点是至关重要的,监管是形成一个递归的故障处理结构。如果你尝试在一个层面上做太多的话,它会变得很难,因此,在这种情况下,建议的方式是增加一个级别的监督。
Akka实现特定形式称为“家长监督”。Actor只能由其他Actor创造,其中最*的Actor是由图书馆提供的,每个Actor都是由其父母监督的。这种限制使得Actor的监督层次结构的形成,并鼓励健全的设计决策。应该指出的是,这也保证了Actor不能孤立或连接到外部监事,否则可能捉住他们。此外,这将产生一个自然的和干净的关机程序(分树的)演员的应用。
上一篇: AKKA笔记2