You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
就像在经济组织中一样,Actor 自然形成等级制度。一个负责监督程序中某个函数的 Actor 可能希望将其任务拆分为更小、更易于管理的部分。为此,它启动了由它监督的子 Actor。在「[这里](https://doc.akka.io/docs/akka/current/general/supervision.html)」解释监督细节的同时,我们将集中讨论本节中的基本概念。唯一的先决条件是要知道每个 Actor 只有一个监督者,这就是创建它的 Actor。
7
+
就像在经济组织中一样,Actor 自然形成等级制度。一个负责监督程序中某个函数的 Actor 可能希望将其任务拆分为更小、更易于管理的部分。为此,它启动了由它监督的子 Actor。在「[这里](https://github.com/guobinhit/akka-guide/blob/master/articles/general-concepts/supervision.md)」解释监督细节的同时,我们将集中讨论本节中的基本概念。唯一的先决条件是要知道每个 Actor 只有一个监督者,这就是创建它的 Actor。
8
8
9
9
Actor 系统的典型特征是,任务被拆分和委托,直到它们变得足够小,可以一块处理。这样做,不仅任务本身结构清晰,而且结果 Actor 可以根据他们应该处理哪些消息、应该如何正常反应以及应该如何处理失败来进行推理。如果一个 Actor 没有处理特定情况的方法,它会向其监督 Actor 发送相应的失败消息,请求帮助。然后,递归结构允许在正确的级别处理故障。
10
10
@@ -13,30 +13,30 @@ Actor 系统的典型特征是,任务被拆分和委托,直到它们变得
- 如果一个 Actor 管理另一个 Actor 正在做的工作,例如通过传递子任务,那么管理 Actor 应该监督子 Actor。原因是管理 Actor 知道预期的故障类型以及如何处理。
16
-
- 如果一个 Actor 携带非常重要的数据(即,如果可以避免,其状态不会丢失),则该 Actor 应向其监督的子 Actor 找出任何可能危险的子任务,并处理这些子 Actor 的故障。根据请求的性质,最好为每个请求创建一个新的子级,这样可以简化收集答复的状态管理。这就是 Erlang 的“错误内核模式(`Error Kernel Pattern`)”。
17
-
- 如果一个 Actor 依靠另一个 Actor 来履行职责,它应该观察另一个 Actor 的活动(`liveness`),并在接到终止通知后采取行动。这与监督不同,因为监督方对监督策略没有影响,应该注意的是,单独的功能依赖性并不是决定将某个子 Actor 放在层级中何处的标准。
16
+
- 如果一个 Actor 携带非常重要的数据(即,如果可以避免,其状态不会丢失),则该 Actor 应向其监督的子 Actor 找出任何可能危险的子任务,并处理这些子 Actor 的故障。根据请求的性质,最好为每个请求创建一个新的子级,这样可以简化收集答复的状态管理。这就是 Erlang 的“错误内核模式”。
17
+
- 如果一个 Actor 依靠另一个 Actor 来履行职责,它应该观察另一个 Actor 的活动,并在接到终止通知后采取行动。这与监督不同,因为监督方对监督策略没有影响,应该注意的是,单独的功能依赖性并不是决定将某个子 Actor 放在层级中何处的标准。
18
18
19
19
这些规则总是有例外的,但是不管你是遵守规则还是违反规则,你都应该有一个理由。
20
20
21
21
## 配置容器
22
22
23
-
Actor 系统作为 Actor 的协作集合,是管理共享设施(如调度服务、配置、日志记录等)的自然单元。具有不同配置的多个 Actor 系统可以在同一个 JVM 中共存,没有问题,Akka 本身没有全局共享状态。将其与一个节点内或通过网络连接的 Actor 系统之间的透明通信结合起来,可以看到 Actor 系统本身可以用作功能层次结构中的构建块(`building blocks`)。
23
+
Actor 系统作为 Actor 的协作集合,是管理共享设施(如调度服务、配置、日志记录等)的自然单元。具有不同配置的多个 Actor 系统可以在同一个 JVM 中共存,没有问题,Akka 本身没有全局共享状态。将其与一个节点内或通过网络连接的 Actor 系统之间的透明通信结合起来,可以看到 Actor 系统本身可以用作功能层次结构中的构建块。
24
24
25
25
## Actor 最佳实践
26
26
27
-
1. Actor 应该像好的同事一样:高效地工作,而不是不必要地打扰其他人,并且避免占用资源。翻译成编程,这意味着以事件驱动的方式处理事件并生成响应(或更多请求)。Actor 不应在可能是锁、网络套接字等的外部实体上阻塞(即占用线程时被动等待),除非这是不可避免的;对于后一种情况,请参见下文。
28
-
2. 不要在 Actor 之间传递可变对象。为了确保这一点,最好选择不可变的消息。如果通过将它们的可变状态暴露到外部来破坏 Actor 的封装,则返回正常的 Java 并发域(`concurrency land`),并存在所有的缺点。
27
+
1. Actor 应该像好的同事一样:高效地工作,而不是不必要地打扰其他人,并且避免占用资源。翻译成编程语言,这意味着以事件驱动的方式处理事件并生成响应(或更多请求)。Actor 不应在可能是锁、网络套接字等外部实体上阻塞,即占用线程时被动等待,除非这是不可避免的;对于后一种情况,请参见下文。
28
+
2. 不要在 Actor 之间传递可变对象。为了确保这一点,最好选择不可变的消息。如果通过将它们的可变状态暴露到外部来破坏 Actor 的封装,则会返回正常的 Java 并发域,并存在所有的缺点。
29
29
3. Actor 被设计成行为和状态的容器,接受这一点意味着不经常在消息中发送行为(使用 Scala 闭包可能很诱人)。其中一个风险是不小心在 Actor 之间共享可变状态,而这种对 Actor 模型的违反不幸地破坏了所有属性。
30
-
4. 顶级 Actor 是错误内核(`Error Kernel`)的最核心部分,因此要谨慎地创建它们,并且更倾向于真正的分层系统。这对于故障处理(同时考虑配置的粒度和性能)有好处,而且它还减少了对守护者(`guardian`) Actor 的压力,如果使用过度,这是一个单一的竞争点。
30
+
4. 顶级 Actor 是错误内核的最核心部分,因此要谨慎地创建它们,并且更倾向于真正的分层系统。这对于故障处理(同时考虑配置的粒度和性能)有好处,而且它还减少了对守护者 Actor 的压力,如果使用过度,这是一个单一的竞争点。
31
31
32
32
## 你不应该关心的事
33
-
Actor 系统管理配置为使用的资源,以便运行其包含的 Actor。在一个这样的系统中,可能有数百万的 Actor,毕竟所有的赞歌(`mantra`)都是将他们视为丰富的,并且他们在每个实例的开销只有大约 300 字节。当然,在大型系统中处理消息的确切顺序不受应用程序作者的控制,但这也是无意的。
33
+
Actor 系统管理配置使用的资源,以便运行其包含的 Actor。在一个这样的系统中,可能有数百万的 Actor,毕竟所有的赞歌(`mantra`)都是将他们视为丰富的,并且他们在每个实例的开销只有大约 300 字节。当然,在大型系统中处理消息的确切顺序不受应用程序作者的控制,但这也是无意的。
34
34
35
35
## 终止 ActorSystem
36
36
37
-
当你知道应用程序的所有操作都已完成时,可以调`ActorSystem`的`terminate`方法。这将停止守护者 Actor,而守护者 Actor 又将递归地停止其所有子 Actor,即系统守护者(`system guardian`)。
37
+
当你知道应用程序的所有操作都已完成时,可以调`ActorSystem`的`terminate`方法。这将停止守护者 Actor,而守护者 Actor 又将递归地停止其所有子 Actor,即系统守护者。
当几个 Actor 在等待对方达到某个特定的状态以便能够取得进展时,就会出现死锁(`Deadlock`)。由于没有其他 Actor 达到某种状态(一个`Catch-22`问题),所有受影响的子系统都无法继续运行。死锁与阻塞密切相关,因为 Actor 线程能够无限期地延迟其他线程的进程。
18
+
当多个 Actor 在等待对方达到某个特定的状态以便能够取得进展时,就会出现死锁(`Deadlock`)。由于没有其他 Actor 达到某种状态(一个`Catch-22`问题),所有受影响的子系统都无法继续运行。死锁与阻塞密切相关,因为 Actor 线程能够无限期地延迟其他线程的进程。
19
19
20
20
在死锁的情况下,没有 Actor 可以取得进展,相反,当有 Actor 可以取得进展,但可能有一个或多个 Actor 不能取得进展时,就会发生饥饿(`Starvation`)。典型的场景是一个调度算法,它总是选择高优先级的任务而不是低优先级的任务。如果传入的高优先级任务的数量一直足够多,那么低优先级任务将永远不会完成。
-**注释**:Akka 提供的关于在给定的两个 Actor 之间发送的消息的唯一保证是,他们的顺序始终保持不变。详见「[Message Delivery Reliability](https://doc.akka.io/docs/akka/current/general/message-delivery-reliability.html)」。
27
+
-**注释**:Akka 提供的关于在给定的两个 Actor 之间发送的消息的唯一保证是,他们的顺序始终保持不变。详见「[消息传递可靠性](https://github.com/guobinhit/akka-guide/blob/master/articles/general-concepts/message-delivery-reliability.md)」。
根据这个定义,无等待方法永远不会被阻塞,因此不会发生死锁。此外,由于每个 Actor 都可以在有限的步骤之后(调用完成时)继续进行,因此无等待方法没有饥饿。
36
36
37
-
### 锁自由(Lock-freedom)
38
-
锁自由比等待自由更弱。在无锁调用的情况下,某些方法以有限的步数完成可能导致无限的等待(`infinitely often some method finishes in a finite number of steps`)。这个定义意味着没有死锁的调用是不可能的。另一方面,某些调用以有限的步骤完成的保证不足以保证所有调用最终都完成。换句话说,锁自由不足以保证不发生饥饿。
0 commit comments