使用Akka构建集群(一)

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/53887181 概述 Akka提供的非常吸引人的特性之一就是轻松构建自定义集群,这也是我要选择Akka的最基本原因之一。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/53887181

概述

Akka提供的非常吸引人的特性之一就是轻松构建自定义集群,这也是我要选择Akka的最基本原因之一。如果你不想敲太多代码,也可以通过简单的配置构建一个非常简单的集群。本文为说明Akka集群构建的学习成本低廉,以Akka官网的例子代码出发,进行简单改造后与Spring集成,有关Spring集成的信息你可以选择阅读《Spring与Akka的集成》一文。本文所讲述的是一款十分简便的集群监听器,它通过订阅集群成员的消息,对整个集群的成员进行管理(管理的方式只是打印一行日志)。

Akka集群规范

根据Akka官网的描述——Akka集群特性提供了容错的、去中心化的、基于集群成员关系点对点的,不存在单点问题、单点瓶颈的服务。其实现原理为闲聊协议和失败检查。

集群概念

  • 节点(node):集群中的逻辑成员。允许一台物理机上有多个节点。由元组hostname:port:uid唯一确定。
  • 集群(cluster):由成员关系服务构建的一组节点。
  • 领导(leader):集群中唯一扮演领导角色的节点。
  • 种子节点(seed node):作为其他节点加入集群的连接点的节点。实际上,一个节点可以通过向集群中的任何一个节点发送Join(加入)命令加入集群。

节点状态

这里以Akka官网提供的成员状态状态图为例,如图1所示。


图1

图1展示了状态转换的两个因素:动作和状态。

状态

  • joining:节点正在加入集群时的状态。
  • weekly up:配置了akka.cluster.allow-weakly-up-members=on时,启用的状态。
  • up:集群中节点的正常状态。
  • leaving/exiting:优雅的删除节点时,节点的状态。
  • down:标记为已下线的状态。
  • removed:墓碑状态,表示已经不再是集群的成员。

动作

  • join:加入集群。
  • leave:告知节点优雅的离开集群。
  • down:标记集群为已下线。

配置

本节将要展示构建集群所需要的最基本的配置,几乎不会引入过多的开发成本,一个集群就构建完成了。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的远程调用》一文中的配置有很多不同:

  1. provider不再是akka.remote.RemoteActorRefProvider,而是akka.cluster.ClusterActorRefProvider。这说明ActorRef将由akka.cluster.ClusterActorRefProvider提供;
  2. 增加了cluster配置;

cluster配置详解

首先任何一个集群都需要种子节点,作为基本的加入集群的连接点。本例中以我本地的两个节点(分别监听2551和2552端口)作为种子节点。无论配置了多少个种子节点,除了在seed-nodes中配置的第一个种子节点需要率先启动之外(否则其它种子节点无法初始化并且其它节点也无法加入),其余种子节点都是启动顺序无关的。第一个节点需要率先启动的另一个原因是如果每个节点都可以率先启动,那么有可能造成一个集群出现几个种子节点都启动并且加入了自己的集群,此时整个集群实际上分裂为几个集群,造成孤岛。当你启动了超过2个以上的种子节点,那么第一个启动的种子节点是可以关闭下线的。如果第一个种子节点重启了,它将不会在自己创建集群而是向其它种子节点发送Join消息加入已存在的集群。
注意:除了akka.remote.netty.tcp.port配置项指定的端口不同,所有加入集群节点的application.conf可以完全一样。如果akka.remote.netty.tcp.port未指定,那么Akka会为你随机选择其他未占用的端口。

简单集群监听器

我们创建一个简单的集群监听器SimpleClusterListener(实际上是一个Actor,因为继承了UntypedActor),它向集群订阅MemberEvent(成员事件)和UnreachableMember(不可达成员)两种消息,来对集群成员进行管理(打印),其实现见代码清单1所示。

代码清单1

@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的日志输出如下图所示。


我们再启动第二个种子节点,其配置的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应用的博文如下:

  1. Spring与Akka的集成》;
  2. 使用Akka的远程调用》;
  3. 使用Akka构建集群(一)》;
  4. 使用Akka构建集群(二)》;
  5. 使用Akka持久化——持久化与快照》;
  6. 使用Akka持久化——消息发送与接收》;


后记:个人总结整理的《深入理解Spark:核心思想与源码分析》一书现在已经正式出版上市,目前京东、当当、天猫等网站均有销售,欢迎感兴趣的同学购买。


京东:http://item.jd.com/11846120.html 

当当:http://product.dangdang.com/23838168.html 


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
Python
通过阿里云服务器的公网IP访问django网站
在安全组设置,添加可以访问的端口 搭建django网站,可以参考官方的教程 设置网站的setting.py ALLOWED_HOSTS = ['*'] 启动网站服务 python manage.py runserver 0.
5487 0
|
前端开发 Java API
Spring MVC 数据绑定机制详解:@ModelAttribute vs. @RequestParam 和 @PathVariable
本文深入解析了Spring MVC的数据绑定机制,重点对比了`@RequestParam`、`@PathVariable`和`@ModelAttribute`三种注解的使用场景与功能。`@RequestParam`适用于从查询参数或表单数据中提取简单值;`@PathVariable`用于从URL路径中获取资源标识符;而`@ModelAttribute`则能将多个请求参数自动绑定到Java对象,支持复杂数据结构的处理。通过实际案例分析,帮助开发者根据需求选择合适的注解,提升API设计与表单处理效率。
959 9
|
数据采集 缓存 定位技术
网络延迟对Python爬虫速度的影响分析
网络延迟对Python爬虫速度的影响分析
|
供应链 搜索推荐 数据挖掘
探索增强现实(AR)在零售业的应用
【5月更文挑战第12天】本文探讨了AR技术如何革新零售业,包括虚拟试衣间提升购物效率、产品信息展示增强认知、导航导购优化购物体验及互动营销增加用户粘性。AR技术能提升消费者体验,提高零售业效率,并增强品牌竞争力。随着AR的发展,零售业将迎来更多创新应用。
|
前端开发
react18【系列实用教程】Hooks 闭包陷阱 (2024最新版)含useState 闭包陷阱,useEffect 闭包陷阱,useCallback 闭包陷阱
react18【系列实用教程】Hooks 闭包陷阱 (2024最新版)含useState 闭包陷阱,useEffect 闭包陷阱,useCallback 闭包陷阱
343 0
|
JavaScript 前端开发 API
Vue和React,哪个在移动端开发更适合呢
【4月更文挑战第10天】Vue和React在移动端各有优势。Vue以其简单易用、渐进式开发和性能优化吸引开发者,适合初学者和快速迭代项目。而React凭借强大的生态系统、组件化开发模式和卓越性能,尤其在复杂应用和依赖特定库时更具优势。选择应基于项目需求、团队技术栈及性能要求,可先进行技术调研和原型开发。
600 4
|
虚拟化 iOS开发 MacOS
ultraiso软碟通dmg转iso图文教程
很多想尝试安装MacOS虚拟机的小伙伴可能都会遇到这个问题,下载到的系统安装文件是.dmg格式,而虚拟机软件都不认这个格式,那怎么办呢? 接下来就说一下怎么用ultraiso软碟通将dmg转换iso格式。
2397 0
|
负载均衡 监控 Cloud Native
Service Mesh 的实现原理
【2月更文挑战第20天】
|
机器学习/深度学习 数据采集 开发框架
Python实战案例--车型识别app
Python实战案例--车型识别app
|
存储 Java Shell
【Java项目】拉取公司GitLab项目的教程
【Java项目】拉取公司GitLab项目的教程
781 0

热门文章

最新文章

下一篇
开通oss服务