集群使用
本文档介绍了如何使用Akka Cluster和Cluster API。 有状态或有状态的应用程序:是否使用Akka群集视频是了解使用Akka群集动机的一个很好的入门。
特定的文档主题,请参见:
- 何时何地使用Akka群集
- 集群说明
- 集群成员关系服务
- 更高级别的集群工具
- 滚动升级
- 操作,管理,可观察性
您正在查看新的actor API的文档,以查看Akka Classic文档,请参阅Classic Cluster。
您必须启用序列化才能在集群中的ActorSystem(节点)之间发送消息。 在许多情况下,使用Jackson进行序列化是一个不错的选择,如果您没有其他偏好或限制,我们建议您这样做。
模块信息
要使用Akka Cluster,请在您的项目中添加以下依赖项:
集群API扩展
通过集群扩展,您可以管理任务(如加入,离开和断开)以及订阅集群成员事件(例如MemberUp,MemberRemoved和UnreachableMember),通过事件API获取这些事件。
通过在Cluster扩展上的以下引用来完成此操作:
- 管理器:ActorRef
,其中ClusterCommand是命令,例如:Join,Leave和Down - 订阅:ActorRef
,其中ClusterStateSubscription是GetCurrentState或者订阅、取消订阅集群事件,例如MemberRemoved - 状态:当前的CurrentClusterState
以下所有示例均需要导入以下包:
所需的最低配置是设置用于远程处理的主机/端口,以及akka.actor.provider =“ cluster”。
在每个节点上访问集群扩展:
注意
群集的ActorSystem的名称对于所有成员都必须相同,这是在您启动ActorSystem时传入的。
加入、离开集群
如果未使用配置指定要加入的种子节点,则可以通过管理器以编程方式完成加入集群。
离开集群并关闭节点是相似的:
群集状态更改时,可以使用群集订阅来接收消息。 例如,注册所有MemberEvents,然后使用管理器让节点离开集群,将导致该节点的事件经历Membership Lifecycle。
此示例订阅ActorRef
然后要求节点离开:
有时无需订阅集群事件,而仅通过Cluster.get(system).state()获得完整的成员状态有时会很方便。 请注意,此状态不一定与发布到群集订阅的事件同步。
有关成员事件的详细信息,请参见集群成员。 变更事件有很多类型,有关事件的详细信息,请查阅扩展了akka.cluster.ClusterEvent.ClusterDomainEvent的类的API文档。
订阅集群
加入集群
种子节点是加入集群的初始接触点,可以通过不同的方式完成:
- 使用群集引导程序自动生成
- 配置种子节点
- 以编程方式
在加入过程之后,种子节点并不特殊,它们和其他节点参与集群的方式完全相同。
自动加入Cluster Bootstrap的种子节点
使用开源Akka Management项目的模块Cluster Bootstrap,可以自动发现加入过程的节点。 请参阅其文档以获取更多详细信息。
加入已配置的种子节点
当一个新节点启动时,它会向所有种子节点发送一条消息,然后将join命令发送给最先回答的节点。 如果没有任何种子节点回复(可能尚未启动),它将重试此过程,直到成功或关闭为止。
您可以在配置文件(application.conf)中定义种子节点:
在使用以下语法启动JVM时,也可以将其定义为Java系统属性:
当一个新节点启动时,它会向所有配置的种子节点发送一条消息,然后向最先回答的节点发送一个加入命令。如果没有种子节点答复(可能尚未启动),它将重试此过程,直到成功或关闭为止。
种子节点可以以任何顺序启动。不必使所有种子节点都运行,但是在最初启动集群时,必须启动配置的种子节点列表中第一个种子节点。如果不这样,则其他种子节点将不会被初始化,并且其他节点也无法加入群集。第一个种子节点特殊的原因是启动空集群时,避免形成分离岛式。最快同时启动所有配置的种子节点(顺序无关紧要),否则可能需要配置种子节点超时时间。
一旦启动了两个以上的种子节点,关闭第一个种子节点就没有问题。如果第一个种子节点重新启动,它将首先尝试加入现有群集中的其他种子节点。请注意,如果您同时停止所有种子节点,并使用相同的种子节点配置重新启动它们,它们将加入彼此,并形成一个新集群,而不是加入现有集群的其余节点。这可能是不希望的,可以通过将多个节点列为种子节点来实现冗余,而不是同时停止所有节点。
如果要在不同计算机上启动节点,则需要在application.conf中指定计算机的ip地址或主机名,而不是127.0.0.1。
以编程方式加入种子节点
在启动时通过外部工具或API动态发现其他节点时,以编程方式进行连接很有用。
种子节点地址列表与配置的种子节点具有相同的语义,并且该过程的底层实现是相同的,请参阅加入配置的种子节点。
加入种子节点时,除了被认为是引导群集的第一个种子节点,您不应该包括节点本身。所需的初始种子节点地址应优先放在程序化连接的参数中。
调优联接
将自动重试联系种子节点,直到超时,seed-node-timeout定义了超时时间。在配置了retry-unsuccessful-join-after之后,将自动重试加入特定种子节点。重试意味着它尝试联系所有种子节点,然后加入首先应答的节点。如果种子节点列表中的第一个节点无法在已配置的种子节点超时内与任何其他种子节点联系,则它将加入自身。
默认情况下,给定种子节点的加入将无限重试,直到成功加入为止。如果不成功,可以通过配置超时来中止该过程。中止时,它将运行Coordinated Shutdown,默认情况下将终止ActorSystem。还可以将CoordinatedShutdown配置为退出JVM。如果种子节点是动态组装的,则定义此超时很有用,新的种子节点重新启动失败后,需要重试。
如果您没有配置种子节点或使用联接种子节点函数,则需要使用JMX或HTTP手动加入集群。
您可以加入集群中的任何节点。不必将其配置为种子节点。请注意,您只能加入现有的集群成员,这对于引导来说意味着一个节点必须加入自身,随后的节点可以加入它们以组成集群。
一个actor系统只能加入一次集群,其他尝试将被忽略。actor系统成功加入集群后,必须重新启动它才能再次加入同一集群。重新启动后,它可以使用相同的主机名和端口。当它作为集群中现有成员的新化身出现并尝试加入时,现有成员将被删除,并允许其新化身加入。
离开
有几种从集群中删除成员的方法。
1.推荐的离开群集的方法是正常退出,通知群集节点将离开。当ActorSystem终止时以及从环境发送SIGTERM来停止JVM进程时,由Coordinated Shutdown执行。
2.正常退出也可以使用HTTP或JMX执行。
3.当无法正常退出时,例如,在JVM进程突然终止的情况下,该节点将被其他节点检测到无法访问,并在Downing之后被删除。
与节点的突然终止和关闭相比,节点shutdown时,优雅的下线可以更快切换到其他节点。
当集群节点将自身视为退出时,也将运行 Coordinated Shutdown,即从另一个节点离开将触发离开节点上的关闭过程。使用Akka Cluster时,会自动添加用于正常退出群集的任务,包括正常关闭Cluster Singleton和Cluster Sharding。例如,运行关闭过程还将触发正常退出(如果尚未进行)。
通常,这是自动处理的,但是如果在此过程中出现网络故障,则仍然有必要将节点的状态设置为“关闭”以完成删除操作,请参见关闭。
宕机
在许多情况下,成员可以正常地从群集中退出,如节点下线,但是在某些情况下,需要先执行明确的停机决策才能将其删除。例如,在JVM进程突然终止,无法恢复的系统过载或无法修复的网络分区的情况下。在这种情况下,其他节点将检测到该节点无法访问,但是在将其删除之前,还必须将其标记为“已关闭”。
当故障检测器认为某个成员不可达时,leader节点不允许执行其职责,例如将新加入的成员的状态更改为“ Up”。首先,该节点必须重新变得可访问,否则不可访问成员的状态必须更改为“关闭”。可以自动或手动将状态更改为“关闭”。
我们建议您启用的Split Brain Resolver,这是Akka Cluster模块的一部分。您可以通过配置启用它:
您还应该考虑其他可用的关机策略。
如果未配置Downing提供者,则必须使用HTTP或JMX手动执行Downing。
请注意,Cluster Singleton或Cluster Sharding实体运行在已崩溃(无法访问)节点,运行的实体将不会在另一个节点上启动,直到从集群中删除了先前的节点。做出崩溃的决定后,将删除崩溃的(无法访问的)节点。
还可以使用Cluster.get(system).manager().tell(Down(address()以编程方式执行Downing,但这在测试以及实现DowningProvider时最有用。
如果崩溃的节点重新启动,并使用相同的主机名和端口再次加入群集,则该成员的先前版本将首先被关闭并删除。具有相同主机名和端口的新加入,尝试被用作证明先前的不再存在。
如果节点仍在运行,即将闭时,将其自身视为“关机”。如果将run-coordinated-shutdown-when-down设置为on(默认值),则Coordinated Shutdown将自动运行,但是该节点不会尝试,正常退出群集。
节点角色
并非集群的所有节点都需要执行相同的功能。 例如,可能有一个子集运行Web前端,一个子集运行数据访问层,另一个子集进行数字运算。 选择要在每个节点(例如,支持群集的路由器)上启动的actors,可以考虑节点角色以实现这种职责分配。
节点角色在名为akka.cluster.roles的配置属性中定义,通常在启动脚本中定义为系统属性或环境变量。
角色是您可以订阅的MemberEvent中成员信息的一部分。 自身节点的角色可从selfMember获得,并可用于有条件地启动某些actors:
故障检测
群集中的节点通过发送心跳来相互监控,以检测节点是否与群集的其余部分不可访问。 请参见:
- 故障检测器说明
- Phi应计故障检测器实现
- 使用故障检测器
使用故障检测器
群集默认情况下使用akka.remote.PhiAccrualFailureDetector作为故障检测器,或者您可以通过实现akka.remote.FailureDetector并配置它来提供故障检测器:
在群集配置中,您可能需要根据环境进行调整:
- 当phi值被认为是故障,akka.cluster.failure-detector.threshold
- 突发异常的误差范围,akka.cluster.failure-detector.acceptable-heartbeat-pause
如何测试
Akka提供并使用多种类型的测试策略:
- 测试
- 多节点测试
- 多JVM测试
配置
集群有几个配置属性。有关完整的配置说明,默认值和选项,请参考 reference configuration。
达到群集大小时如何启动
一个常见的用例是在初始化集群,成员加入并且集群达到一定大小之后启动actor。
通过配置选项,您可以定义所需的成员数,然后由leader将成员的成员状态由"Joining"更改为"Up"。
以类似的方式,您可以在leader将成员状态由"Joining"更改为“Up”之前,定义特定角色所需的成员数:
集群信息记录
您可以使用配置属性关闭集群事件的日志记录:
您可以启用群集事件的详细日志记录,info级别,例如用于临时故障排除,配置属性如下:
集群调度
集群扩展是通过actors来实现的。为了保护它们免受用户actors的干扰,默认情况下,它们在akka.actor.internal-dispatcher配置的内部调度程序上运行。可以设置akka.cluster.use-dispatcher将集群actors进一步隔离到其自己的调度程序上,或者使其在同一调度程序上运行以减少线程数。
配置兼容性检查
创建集群是部署两个或更多节点,组成一个应用程序。因此,为群集中的所有节点配置兼容设置非常重要。
配置兼容性检查功能可确保群集中的所有节点都具有兼容配置。每当新节点加入现有群集时,其配置设置的子集(仅那些需要检查的设置)都会发送到群集中的节点以进行验证。在集群端检查配置后,集群将发回一组必需的配置。然后,加入节点将验证其是否符合集群配置。如果节点、集群都通过所有检查,加入节点将继续进行。
可以通过扩展akka.cluster.JoinConfigCompatChecker添加新的自定义检查器,将其包括在配置中。每个检查器都必须与一个唯一的key相关联:
注意
配置兼容性检查默认情况下处于启用状态,但可以通过设置akka.cluster.configuration-compatibility-check.enforce-on-join = off,禁用它。这在执行滚动升级时特别有用。显然,只有在无法完全关闭群集的情况下,才应该这样做。集群节点有不同的配置设置,可能会导致数据丢失或数据损坏。仅可以在加入节点上禁用此设置。始终在两侧进行检查,并记录警告。在不兼容的情况下,加入节点有责任决定是否应中断该过程。
如果要使用Akka 2.5.9或更早版本(不支持此功能)在群集上执行滚动升级,则将不会执行检查,因为正在运行的群集无法验证加入节点发送的配置,也无法发送自己的配置。
高级别集群工具
集群单例
在某些用例中,确保集群中某处仅运行某种类型的一个actor很方便,也有必要。可以通过订阅成员事件来实现,但是要考虑一些特殊情况。因此,群集单例涵盖了此特定用例。
集群分片
将actors分布在集群中的多个节点上,并支持使用其逻辑标识符与actors交互,而不必关心actor在集群中的物理位置。
请参阅 Cluster Sharding。
分布式数据
当您需要在Akka群集中的节点之间共享数据时,分布式数据很有用。使用提供键值存储(例如API)的actor访问数据。
请参阅Distributed Data。
分布式发布订阅
集群中actors之间基于主题的发布-订阅消息,即发送者不必知道目标actor正在哪个节点上运行。
请参阅 Distributed Publish Subscribe。
集群感知路由器
使用路由策略(例如轮询和一致性哈希)将消息分发给群集中不同节点上的actor。
请参阅Group Routers。
跨多个数据中心集群
Akka群集可以跨多个数据中心,可用性分区、区域,因此一个群集可以跨越多个数据中心,并且仍然可以容忍网络分区。
请参阅 Cluster Multi-DC。
可靠传递
集群actors之间,消息可靠传递、流程控制。
示例工程
Cluster example project是一个示例项目,可以下载,附有如何运行的说明。
该项目包含一些示例,这些示例说明了集群的不同功能,例如,订阅集群成员事件,以及使用支持集群的路由器,向集群中节点上运行的actors发送消息。