Akka群集的核心是群集成员,以跟踪哪些节点是群集的一部分,及其运行状况。使用gossip和故障检测来传播群集成员关系。
在群集成员关系服务之上构建了一些高级群集工具。
介绍
集群由一组成员节点组成。每个节点的标识符是主机名:端口:uid元组。 Akka应用程序可以分布在群集中,每个节点负责应用程序的部分功能。集群成员与在该应用程序的节点上运行的actors是分离的。节点可以是群集的成员,而无需托管任何actors。通过向群集中要加入的节点之一发出“加入”命令来加入群集。
节点标识符在内部还包含一个UID,该ID用hostname:port上唯一标识此actor系统实例。 Akka使用UID能够可靠地触发远程死亡监控。这意味着从同一集群中删除后,该actor系统再也无法加入该集群。要将具有相同hostname:port的actor系统重新加入集群,您必须停止actor系统,并启动一个具有相同hostname:port的新系统,然后它将接收到不同的UID。
成员状态
群集成员状态是特殊的CRDT,这意味着它具有单点聚合功能。当不同节点上并发更改时,更新始终可以合并、收敛到相同的最终结果。
- joining-加入集群时的瞬时状态
- weakly up -网络分裂时的过渡状态(仅当akka.cluster.allow-weakly-up-members = on时)
- up-正常运行状态
- leaving/exiting-正常移除期间的状态
- down-标记为down(不再是集群决策的一部分)
- removed-逻辑删除状态(不再是集群成员)
成员事件
跟踪成员生命周期的事件是:
- ClusterEvent.MemberJoined-新成员已加入集群,其状态已更改为Joining
- ClusterEvent.MemberUp-新成员已加入集群,其状态已更改为Up
- ClusterEvent.MemberExited-成员正在离开集群,其状态已更改为“Exiting”。请注意,当此事件已经发送到另一个节点上时,该节点可能已经关闭。
- ClusterEvent.MemberRemoved-从集群中完全删除的成员。
- ClusterEvent.UnreachableMember-该节点不可达,由至少一个其他节点的故障检测器检测到。
- ClusterEvent.ReachableMember-成员在不可访问之后,再次被认为是可访问的。先前将其检测为不可达的所有节点,将其再次检测为可达。
成员生命周期
通过调用联接操作,将节点置于联接状态,将节点引入集群。一旦所有节点都知道新节点正在加入(通过gossip收敛),领导者将把成员状态设置为up。
如果节点以安全的、预期方式离开群集,例如通过coordinated shutdown,则它将调用leave操作,将其切换到离开状态。一旦领导者在离开状态下看到节点收敛后,领导者便会将其移至exiting。一旦所有节点都看到退出状态(收敛),领导者就会从群集中删除该节点,并将其标记为已删除。
如果节点不可访问,那么gossip融合是不可能的,因此大多数领导者行为都是不可能的(例如,允许节点成为集群的一部分)。为了能够继续,该节点必须再次变得可访问,或者必须明确将节点“关闭”。这是必需的,因为无法访问的节点的状态是未知的,并且群集无法知道该节点是否已崩溃,或由于网络问题或GC暂停而暂时无法访问。请参阅下面有关用户操作的部分,以了解如何关闭节点。
节点上的actor系统退出或关闭后,无法再次加入集群。特别是,节点在无法访问时被关闭,随后重新获得连接也无法重新加入群集。相反,必须在节点上重新启动该过程,创建一个新的actor系统,该系统可以再次执行joining过程。
一种特殊情况,在不经历leaving或downing过程的情况下重新启动节点,例如托管该节点的计算机意外重新启动。当节点的新实例尝试重新加入群集时,群集可能仍然认为旧实例不可访问。但是,在这种情况下,很显然旧节点已消失,因为新实例与其旧实例有相同的地址(主机和端口)。在这种情况下,先前的实例将被自动标记为已关闭,而新实例可以在无需人工干预的情况下重新加入群集。
Leader
领导者的目的是在达到收敛时,确认状态变化。gossip收敛后,领导者可以由每个节点明确地确定。根据当前群集的组成,可能要求任何节点都扮演领导者的角色。
没有收敛,不同的节点可能对哪个节点是领导者有不同的看法。因此,只有在存在收敛,才允许大多数领导者动作,以确保所有节点都同意集群的当前状态,并且状态更改源自单个节点。大多数常规状态更改(例如将节点从joining更改为up)都是这种类型的。
在其他情况下,即使当前无法达到收敛,也需要采取措施。值得注意的是,如果故障检测器确定群集中的一个或多个节点当前不可达,则无法达到收敛。在这种情况下,群集可能会被划分(脑裂场景),并且每个分区可能对哪些节点可访问、哪些节点无法访问有自己的看法。在这种情况下,分区两侧的节点可能会将自己视为可达节点的领导者。领导者在这种情况下执行的任何操作用这种方式设计:所有并发领导者得出相同结论(通常这是不可能的,只有在附加约束条件下才可行)。此类情况中最重要的情况是脑裂,需要手动或自动关闭节点以使群集恢复融合。
Split Brain Resolver是该程序内置的实现方案。
无需收敛的另一种可能过渡,是将成员标记为WeaklyUp,如下一节所述。
WeaklyUp 成员
如果节点不可达,则gossip收敛是不可能的,因此大多数领导者行为是不可能的。通过启用akka.cluster.allow-weakly-up-members(默认情况下启用),即使尚未达到收敛,也可以将加入节点提升为WeaklyUp。一旦再次建立gossip收敛,领导者就会将WeaklyUp成员改为Up。
您可以订阅WeaklyUp成员关系事件,以利用处于这种状态的成员,但是您应该知道,网络分区另一侧的成员不知道新成员的存在。例如,您不应该在法定决策中计算WeaklyUp成员。
状态图
成员状态图
用户动作
- join-将单个节点加入集群-如果已在配置中指定了要加入的节点,则在启动时可以是显式的或自动join
- leave-告诉节点正常离开集群,协调关闭通过ActorSystem或JVM关闭触发
- down-将节点标记为down。需要执行此操作才能从群集中删除崩溃的节点(未“leave”)。它可以通过集群HTTP管理手动触发,也可以由诸如Split Brain Resolver之类的崩溃提供程序自动触发
Leader动作
领导者有责任确认用户将成员移入或移出集群的操作:
- joining ⭢ up
-joining ⭢ weakly up(执行此领导者操作不需要收敛,即使存在无法到达的节点也能生效)
- weakly up ⭢ up(再次达到完全收敛后)
- leaving ⭢ exiting
- exiting ⭢ removed
- down ⭢ removed
故障检测和不可达性
不可访问不是一个单独的成员状态,而是一个除状态之外的标志。监控另一个节点的每个节点上的故障检测器可以将被监视的节点标记为不可访问,而与它的状态无关。之后,故障检测器将继续监视节点,直到它再次检测到该节点可到达,并删除该标志。仅在所有监视节点都认为该节点可再次到达后,该节点才被视为可再次到达。