提交 69336c3d 编写于 作者: 梦境迷离's avatar 梦境迷离

fix 路径地址引用,时间:2019-11-10 13:24:42

上级 8d5b36ba
......@@ -15,16 +15,16 @@ description: 本章描述了如何在可能的分布式actor系统中识别和
### 什么是actor的引用
actor引用是ActorRef的子类型,其首要目的是支持向它表示的actor发送消息。每个actor都可以通过自身字段访问其规范的(本地)引用。默认情况下,此引用存在于发送给其他actor的所有消息的发件人引用中。相反,在消息处理期间,actor可以通过sender()方法访问表示当前消息的发送者的引用
actor引用是ActorRef的子类型,其首要目的是支持向它表示的actor发送消息。每个actor都可以通过自身字段访问其规范的(本地)引用。默认情况下,此引用存在于发送给其他actor的所有消息的发件人引用中。相反,在消息处理期间,actor可以通过sender()方法访问表示当前消息的发送者的引用。sender()是一个函数而不是val,使用时需要注意其变化
根据actor系统的配置,支持几种不同类型的actor引用:
* 纯本地actor引用被未配置为支持网络功能的actor系统使用。如果通过网络连接发送到远程JVM,这些actor引用将无法工作。
* 启用远程处理后的本地actor引用由actor系统使用,这些actor系统支持那些表示同一JVM中的actor的引用的联网功能。为了在发送到其他网络节点时也是可以联系的,这些引用包括协议和远程寻址信息。
* 有一个本地actor引用的子类型用于路由器(即,在Router trait中混合的actor)。它的逻辑结构与上述本地引用的逻辑结构相同,但是向他们发送消息会直接分派给他们的一个孩子。
* 有一个本地actor引用的子类型用于路由器(即,在Router trait中混合的actor)。它的逻辑结构与上述本地引用的逻辑结构相同,但是向他们发送消息会直接分派给他们的一个孩子。
* 远程actor引用表示可以使用远程通信访问的actor,即向它们发送消息将透明地序列化消息并发送给远程JVM。
* 在所有实际目的中,有几种特殊类型的actor引用与本地actor引用类似:
* PromiseActorRef是Promise的特殊表示形式,目的是通过actor的响应来完成。 akka.pattern.ask创建此actor 引用。
* PromiseActorRef是Promise的特殊表示形式,目的是通过actor的响应来完成。 akka.pattern.ask创建此actor引用。
* DeadLetterActorRef是死信服务的默认实现,Akka将所有目的地已关闭或不存在的消息路由到死信服务。
* Akka在查找不存在的本地actor路径时返回的是EmptyLocalActorRef:它等效于DeadLetterActorRef,但它保留其路径,以便Akka可以通过网络发送该路径并将其与该路径的其他现有actor引用进行比较,其中可能是在actor去死亡之前获得的。
* 还有一些一次性的内部实现,您永远不应该看到:
......@@ -55,24 +55,24 @@ actor对旧化身的引用对于新的化身是无效的。发送给旧的actor
"akka://my-sys/user/service-a/worker1" // purely local
"akka.tcp://my-sys@host.example.com:5678/user/service-b" // remote
```
在这里,akka.tcp是2.4版本的默认远程传输工具。其他的传输工具是可插拔的。主机和端口部分的说明(即示例中的host.example.com:5678)取决于所使用的传输机制,但必须遵守URI结构规则。
在这里,akka.tcp是2.4版本的默认远程传输工具。其他的传输工具是可插拔的。主机和端口部分的说明(即示例中的host.example.com:5678)取决于所使用的传输机制,但必须遵守URI结构规则。
#### 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系统或JVM。这意味着,如果某个actor的祖先之一受到远程监视,则其逻辑路径(监督层次结构)和物理路径(actor远程部署)可能会发生分歧。
一个重要的方面是,actor的物理路径从不跨越多个actor系统或JVM。这意味着,如果某个actor的祖先之一受到远程监视,则其逻辑路径(监督层次结构)和物理路径(actor远程部署)可能会发生分歧。
#### actor路径别名或符号链接
在一些真正的文件系统中,您可能会想到一个actor的“路径别名”或“符号链接”,也就是说,一个actor可以使用多条路径到达。
但是,您应该注意到,actor层次结构与文件系统层次结构不同。您不能像符号链接那样自由地创建actor路径来引用任意的actor。
正如上面的actor逻辑路径和物理路径部分所描述的那样,actor路径必须是表示监视层次结构中的逻辑路径,或者是代表actor远程部署的物理路径。
正如上面的actor逻辑路径和物理路径部分所描述的那样,actor路径必须是表示监视层次结构中的逻辑路径,或者是代表actor远程部署的物理路径。actor的层次结构一般指的是actor树形结构中的拓扑,独立的actor对象是没有意义的,所以actor一般有其父母与孩子。并且一个actor系统至少存在三个actor。(root,system,user)。下文的逻辑层次结构也是指actor的拓扑图。
### 如何获得actor的引用
......@@ -81,12 +81,12 @@ actor对旧化身的引用对于新的化身是无效的。发送给旧的actor
#### 创建actor树
通常,通过使用ActorSystem.actorOf方法在监护actor下创建actor,然后从创建的actor中使用ActorContext.actorOf来启动actor系统,以生成actor树结构。这些方法返回对新创建的actor的引用。
每个actor都可以直接访问(通过其ActorContext)其父代,自身和子代的引用。这些引用可以在消息内发送给其他actor,从而使他们能够直接回复消息。
每个actor都可以直接访问(通过其ActorContext)其父代,自身和子代的引用。这些引用可以在消息内发送给其他actor,从而使他们能够直接回复消息。
#### 通过具体路径查找actor
此外,可以使用ActorSystem.actorSelection方法查找actor引用。该选择可以用于与所述actor进行通信,并且在传递每个消息时查找与该选择相对应的actor。
要获取绑定到特定actor生命周期的ActorRef,您需要向actor发送消息(例如内置的Identify消息),并使用接收者actor回复的sender()引用。
要获取绑定到特定actor生命周期的ActorRef,您需要向actor发送消息(例如内置的Identify消息),并使用接收者actor回复的sender()引用。
#### 绝对路径与相对路径
......@@ -107,7 +107,7 @@ context.actorSelection("/user/serviceA") ! msg
#### 查询逻辑的actor层次结构
由于actor系统形成了类似层次结构的文件系统,所以路径匹配与Unix Shell所支持的方式是一样的:您可以用通配符(*和?)替换路径元素名称(*和?),以形成可能匹配零或多个实际actor的选择。
由于actor系统形成了类似层次结构的文件系统,所以路径匹配与Unix Shell所支持的方式是一样的:您可以用通配符*和?)替换路径元素名称(*和?),以形成可能匹配零或多个实际actor的选择。
因为结果不是单个actor引用,所以它有一个不同类型的ActorSelection,并且不支持ActorRef所做的全部操作集。
可以使用ActorSystem.actorSelection和ActorContext.actorSelection方法来制定选择,并支持发送消息:
......@@ -115,23 +115,23 @@ context.actorSelection("/user/serviceA") ! msg
context.actorSelection("../*") ! msg
```
将向包括当前actor在内的所有兄弟姐妹发送msg。对于使用ActorSelection获得的引用,要执行消息发送,需要遍历监督层次结构。
将向包括当前actor在内的所有兄弟姐妹发送msg。对于使用actorSelection获得的引用,要执行消息发送,需要遍历监督层次结构。
由于匹配所选内容的actor的确切集合可能会发生变化,甚至在消息发送给收件人时也可能发生变化,因此在活跃变化时不可能查看所选内容的确切内容。
为了做到这一点,通过发送请求和收集所有答案,提取发件人引用,然后观察所有发现的具体actor,来解决不确定性。这种解决选择的方案可以在将来的发行版中加以改进。
总结:actorOf与actorSelection
actorOf只会创建一个新的actor,并将其作为调用此方法的上下文的直接子代(可以是任何actor或actor系统)
actorOf只会创建一个新的actor,并将其作为调用此方法的上下文的直接子代(可以是任何actor或actor系统)
actorSelection仅在传递消息时查找现有的actor,即不创建actor,或在创建选择时验证actor的存在
### actor引用与路径相等性
ActorRef的相等性与ActorRef对应于目标actor化身的意图相匹配。当两个actor引用具有相同的路径并指向相同的actor化身时,比较它们时是相等的。
指向终止的actor的引用不等于指向具有相同路径的另一个(重新创建的)actor的引用。
指向终止的actor的引用不等于指向具有相同路径的另一个(重新创建的)actor的引用。
请注意,由于故障导致的actor重新启动仍然意味着它是同一actor的化身,即ActorRef的使用者看不到重新启动。
如果需要跟踪集合中的actor引用,而不关心确切的actor化身,则可以使用ActorPath作为键,因为在比较actor路径时不会考虑目标actor的标识符。
从这也可以看出,实际上路径(path)是actor的名称,后面跟着的是actor的唯一标识符id,大多数情况下可以忽略这个id的存在。如下:
从这也可以看出,实际上路径(path)是actor的名称,后面跟着的是actor的唯一标识符id,大多数情况下可以忽略这个id的存在。如下:
```
First: Actor[akka://testSystem/user/first-actor#1053618476] //akka是协议,表示是本地actor
......@@ -141,11 +141,11 @@ Second: Actor[akka://testSystem/user/first-actor/second-actor#-1544706041] //sec
### 重用actor路径
当actor终止时,它的引用将指向死信邮箱,DeathWatch将发布其最终过渡,并且通常不希望它再次出现(因为actor的生命周期不允许这样做)
尽管以后可以使用相同的路径创建一个actor(由于在不保持所有创建的actor可用的情况下就不可能强制执行相反的操作)是一种不好的做法:
当actor终止时,它的引用将指向死信邮箱,DeathWatch将发布其最终过渡,并且通常不希望它再次出现(因为actor的生命周期不允许这样做)
尽管以后可以使用相同的路径创建一个actor(由于在不保持所有创建的actor可用的情况下就不可能强制执行相反的操作)是一种不好的做法:
通过actorSelection发送给actor的消息“死亡”的人突然又开始工作了,但是并没有保证在此过渡和任何其他事件之间顺序,因此,该路径的新居民可能会收到发往前一个租户的消息。
在非常特殊的情况下这样做可能是正确的,但是请确保将其处理仅限于actor的上司(主管),因为这是唯一能够可靠地检测到正确注销的actor的名称,在此之前,新子女的创建将失败。
在非常特殊的情况下这样做可能是正确的,但是请确保将其处理仅限于actor的上司(主管、上级),因为这是唯一能够可靠地检测到正确注销的actor的名称,在此之前,新子女的创建将失败。
在测试期间,当测试主题依赖于在特定路径上实例化时,它也可能是必需的。在这种情况下,最好是模拟其主管,以便它将终止的消息转发到测试过程中的适当点,使后者能够等待名称的正确注销。
......@@ -153,7 +153,7 @@ Second: Actor[akka://testSystem/user/first-actor/second-actor#-1544706041] //sec
当actor创建子actor时,actor系统的部署程序将决定新actor是驻留在同一个JVM中,还是驻留在另一个节点上。在第二种情况下,
将通过网络连接来触发actor的创建,这种连接发生在不同的JVM中,因此也会发生在不同的actor系统中。远程系统将将新actor置于为此目的保留的特殊路径之下,
而新actor的主管将是远程actor的引用(代表触发其创建的该actor)。在这种情况下,context.parent(主管引用)和context.path.parent(actor路径中的父节点)并不表示相同的actor。
而新actor的主管将是远程actor的引用(代表触发其创建的该actor)。在这种情况下,context.parent(主管引用)和context.path.parent(actor路径中的父节点)并不表示相同的actor。
但是,在监控程序中查找子节点的名称会在远程节点上找到,从而保持逻辑结构,例如,当发送到未解析到的actor引用时。
![actor本地与远程的交互](../public/image/actor-local-remote.png)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册