Akka提供的很是吸引人的特性之一就是轻松构建自定义集群,这也是我要选择Akka的最基本缘由之一。若是你不想敲太多代码,也能够经过简单的配置构建一个很是简单的集群。本文为说明Akka集群构建的学习成本低廉,以Akka官网的例子代码出发,进行简单改造后与Spring集成,有关Spring集成的信息你能够选择阅读《Spring与Akka的集成》一文。本文所讲述的是一款十分简便的集群监听器,它经过订阅集群成员的消息,对整个集群的成员进行管理(管理的方式只是打印一行日志)。html
根据Akka官网的描述——Akka集群特性提供了容错的、去中心化的、基于集群成员关系点对点的,不存在单点问题、单点瓶颈的服务。其实现原理为闲聊协议和失败检查。java
这里以Akka官网提供的成员状态状态图为例,如图1所示。node
图1spring
图1展现了状态转换的两个因素:动做和状态。bash
本节将要展现构建集群所须要的最基本的配置,几乎不会引入过多的开发成本,一个集群就构建完成了。application.conf文件的内容以下:架构
akka { actor { provider = "akka.cluster.ClusterActorRefProvider" } remote { log-remote-lifecycle-events = off netty.tcp { hostname = "127.0.0.1" port = 2551 } } cluster { seed-nodes = [ "akka.tcp://metadataAkkaSystem@127.0.0.1:2551", "akka.tcp://metadataAkkaSystem@127.0.0.1:2552"] #//#snippet # excluded from snippet auto-down-unreachable-after = 10s #//#snippet # auto downing is NOT safe for production deployments. # you may want to use it during development, read more about it in the docs. # # auto-down-unreachable-after = 10s # Disable legacy metrics in akka-cluster. metrics.enabled=off } }
此配置文件与我在《使用Akka的远程调用》一文中的配置有不少不一样:app
咱们建立一个简单的集群监听器SimpleClusterListener(其实是一个Actor,由于继承了UntypedActor),它向集群订阅MemberEvent(成员事件)和UnreachableMember(不可达成员)两种消息,来对集群成员进行管理(打印),其实现见代码清单1所示。tcp
代码清单1ide
@Named("SimpleClusterListener") @Scope("prototype") public class SimpleClusterListener extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); Cluster cluster = Cluster.get(getContext().system()); // subscribe to cluster changes @Override public void preStart() { // #subscribe cluster.subscribe(getSelf(), ClusterEvent.initialStateAsEvents(), MemberEvent.class, UnreachableMember.class); // #subscribe } // re-subscribe when restart @Override public void postStop() { cluster.unsubscribe(getSelf()); } @Override public void onReceive(Object message) { if (message instanceof MemberUp) { MemberUp mUp = (MemberUp) message; log.info("Member is Up: {}", mUp.member()); } else if (message instanceof UnreachableMember) { UnreachableMember mUnreachable = (UnreachableMember) message; log.info("Member detected as unreachable: {}", mUnreachable.member()); } else if (message instanceof MemberRemoved) { MemberRemoved mRemoved = (MemberRemoved) message; log.info("Member is Removed: {}", mRemoved.member()); } else if (message instanceof MemberEvent) { // ignore } else { unhandled(message); } } }
logger.info("Start simpleClusterListener"); final ActorRef simpleClusterListener = actorSystem.actorOf(springExt.props("SimpleClusterListener"), "simpleClusterListener"); actorMap.put("simpleClusterListener", simpleClusterListener); logger.info("Started simpleClusterListener");
咱们首先启动第一个种子节点,配置跟第一小节彻底一致。咱们观察SimpleClusterListener的日志输出以下图所示。post
咱们再启动第二个种子节点,其配置的akka.remote.netty.tcp.port为2552,咱们观察SimpleClusterListener的日志输出以下图所示。
咱们再启动一个非种子节点,没有为其指定akka.remote.netty.tcp.port,咱们观察SimpleClusterListener的日志输出以下图所示。
能够看到新加入的节点信息被SimpleClusterListener打印出来了,细心的同窗可能发现了一些Akka集群中各个节点的状态迁移信息,第一个种子节点正在加入自身建立的集群时的状态时JOINING,因为第一个种子节点将本身率先选举为Leader,所以它还将本身的状态改变为Up。后面它还将第二个种子节点和第三个节点从JOINING转换到Up状态。
咱们中止第三个加入的节点,咱们观察SimpleClusterListener的日志输出以下图所示。
能够看到其状态首先被标记为Down,最后被转换为Removed。
经过以上介绍相信你们对使用Akka构建集群有了基本的认识,是否是很轻松?若是想要继续了解如何使用Akka构建集群,请阅读《使用Akka构建集群(二)》。