说到Nacos首先会想到它的注册中心和配置中心,本篇以注册中心入手,来聊聊以下部分的内容
1.注册中心是个什么东西,它能实现什么效果
2.它提供了哪些核心的功能,整体的脉络
3.核心的注册表结构为何如此设计
4.源码中应用的一些核心设计思想
注册中心是什么
在这个模块主要做两个事
- 解释什么是注册中心
- 打通客户端与服务端关系
注册中心用大白话去理解,当我们服务越来越多,服务间调用也很频繁时,进行统一的管理我们服务的注册、发现、健康检查这些事。
我将源码拉下来以后,编译的过程遇到了很多的问题,比如提示com.alibaba.nacos.consistency.entity包缺失,还有一些其他的坑踩完只剩这个点没解决,真的是太恼火了,查了很多的解决方案,说是这个包是通过protobuf协议写入的,需要经过编译。尝试了几种方式,就是那种别人可以解决,自己一试就费。这个问题我留在搞懂protobuf之后再攻克,先继续向下。
然后启动主类入口,关于Nacos如何找启动类,可以这样子理解,Nacos的本质是一个SpringBoot的Web应用,而我们熟悉的这个应用都有一个xxApplication的启动类,这是其中一点思路。当我们在服务器上部署时,一般会提供一个启动脚本,比如Nacos就是这个对应安装目录的bin目录下startup.sh脚本,打开脚本看看。
vim startup.sh
这个脚本中有很多有价值的信息,比如JVM参数等,可以根据自己的程序、资源情况进行调整。然后一般呢在启动脚本中有nohup..什么的就可能是启动程序的脚本,比如这里
找到nacos.nacos,尝试在项目中找nacos.nacos,找到了
第一步:启动Server端服务
第一种方式:命令行方式启动单节点
bin/startup.sh -m standalone
第二种方式:如果在本地编译后启动直接按照SpringBoot的方式启动即可,单机启动需要在启动配置项中添加一下这段配置,让项目以单机方式运行。
这里采用第二种方式启动,查看本地Nacos服务是否启动成功:http://localhost:8848/nacos 默认用户名密码都是 nacos
标志性小图标
启动成功
可以看到服务端已经准备完毕了。
第二步 启动客户端
接下来做两件事:
1.启动客户端 观察是否注册成功
2.服务端注册接口开启断点 观察是否可以正常调通
这里我启动了一个windService的服务,这个官网有demo,直接clone下来跑也可以,然后观察一下注册情况。
可以发现此时已经注册成功了。接下来验证第二点,找到注册实例的接口,在那打个断点。
然后客户端服务windService重新启动,观察断点情况。
可以看到,正常的流程已经打通了,接下来我们就可以愉快的看源码了,像看我们自己开发的项目一样,看API、学习、调试.. 至于为什么把断点打在这,接着往下看。
注册中心有哪些功能
学习一门技术前,先了解它有哪些功能,看API文档无疑是最快建立起印象的。Nacos官网的用户指南中提供了API详细的信息,接口功能、参数信息、错误编码,我们可以通过调试接口来加速学习,官网地址:Nacos文档
核心功能
可以看到,大概分成了配置管理、服务发现以及命名空间三部分,我写了几个简短描述的如下图,详细的可以去官网查阅,从注册实例的描述也可以理解了为什么我把客户端注册实例的断点打到了这个接口中了
整体脉络
在正式看源码之前,还有两个障碍要扫除,其中之一就是整体脉络。所谓的整体脉络也是指当我的客户端接入到Nacos以后,接下来的一整套流程要如何运转。以公司实际的项目为例,现在我有两套服务的集群要注册到Nacos上去,分别是活动和卡券。
前提:当活动完成以后根据任务的奖励要给用户发卡或者券,活动调用卡券
- 首先服务都
注册到注册中心上去 - 同时会定期检测每个服务的
心跳 - 对于活动而言,需要调用卡券,所以会通过注册中心进行
服务发现 - 客户端本地一般会利用
负载均衡策略(比如通过ribbon等),比如某个卡券服务出问题,切换到另外的服务上 - 服务端保存注册信息的是
注册表 - 如果Nacos是集群部署还会有
集群数据同步任务等
注册表结构
注册表在Nacos中是一个非常重要的结构,先把这个概念搞懂了,对于理解一些设计问题很有帮助。在源码中注册表的定义是一个serviceMap,如下
/**
* Map(namespace, Map(group::serviceName, Service)).
*/
private final Map<String, Map<String, Service>> serviceMap = new ConcurrentHashMap<>();
可以看出,这是一个双层Map,第一层的key是namespace,即命名空间。value又是一个Map。第二层Map的key是一个group::serviceName,value是一个Service。但是为什么要这么设计呢?
主要还是基于支持多场景的扩展功能,比如公司很小,资源都很紧张,想用一套注册中心就部署dev、test、预发、生产环境,那么可以用namespace做环境隔离。第二层Map又支持以服务组的形式的隔离,而Service中包含的cluster字段又支持集群隔离,所以Nacos可以满足不同隔离级别的设计,也是基于注册表来实现的,当然如果不需要这么多,直接使用默认的也可以。
架构设计精髓
学习源码框架最好是能学习到一点它设计的思想,学到一点赚到一点。基于此部分学习,我领会到的一些是。
- 设计注册实例是只管丢到内存队列中,会有一个异步的线程不断的取任务处理
- 防止多节点操作实例数据的并发问题,用到了写时复制的思想,即在副本中修改数据,修改完再做替换
Nacos中需要学习的还有很多,这只是一个开始。