目标
nacos 作为我们开发中的反响比较好的一个中间件,希望能通过学习它 对我们未来的设计 和 代码编程能力 有更大的影响,学习其先进的思想,相信会让我们 形成自己的思考 并完善自己
项目背景
Nacos 偏 AP 分布式系统的设计、全异步事件驱动的高性能架构和面向失败设计的高可用设计理念
⼀个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
设计原则
极简原则,简单才好用,简单才稳定,简单才易协作。
架构⼀致性,⼀套架构要能适应开源、内部、商业化(公有云及专有云)3 个场景。 扩展性,以开源为内核,商业化做基础,充分扩展,方便用户扩展。 模块化,将通用部分抽象下沉,提升代码复用和健壮性。
长期主义,不是要⼀个能支撑未来 3 年的架构,而是要能够支撑 10 年的架构。 开放性,设计和讨论保持社区互动和透明,方便大家协作。
组成
Configserver 非持久注册中心
VIPServer 持久化注册中心
Diamond 配置中心
需要支持动态修改配置
需要动态变更有多实时
变更快了之后如何管控控制变更风险,如灰度、回滚等
敏感配置如何做安全配置
配置快照
Nacos 的客户端 SDK 会在本地生成配置的快照。当客户端无法连接到Nacos Server 时,可以使用配置快照显示系统的整体容灾能力。配置快照类似于 Git 中的本地 commit,也类似于缓存,会在适当的时机更新,但是并没有缓存过期(expiration)的概念
项目初 运行
下载源代码
如果你能连接 github,可以使用 git@github.com:alibaba/nacos.git
否则 请使用gitee.com/mirrors/Nac…
把代码下载到本地
启动问题
项目启动的时候 发现报 entity 找不到,是因为 protoc 没有生成entity呢。
先查询
是否已经安装,如果你已经安装了,看一下
是否有你要的entity呢,如果没有,执行
就可以看到 已经生成了 entity文件了
但是到这一步 还没完事,点击
怎么加上呢?选择
运行项目
搭建一个mysql, 然后在 console 的resource中 application.properties 文件进行修改
spring.sql.init.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://xxx:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=xxx
url 账号密码换成自己的。
找到 console下面的Nacos 类,执行Debug 运行
运行项目的报错
errCode: 102, errMsg: dataSource or tableName is null
报错信息:
Caused by: com.alibaba.nacos.api.exception.runtime.NacosRuntimeException: errCode: 102, errMsg: dataSource or tableName is null
at com.alibaba.nacos.plugin.datasource.MapperManager.findMapper(MapperManager.java:102)
at com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoPersistServiceImpl.findConfigMaxId(ExternalConfigInfoPersistServiceImpl.java:612)
at com.alibaba.nacos.config.server.service.dump.processor.DumpAllProcessor.process(DumpAllProcessor.java:51)
at com.alibaba.nacos.config.server.service.dump.DumpService.dumpConfigInfo(DumpService.java:317)
at com.alibaba.nacos.config.server.service.dump.DumpService.dumpOperate(DumpService.java:230)
... 40 common frames omitted
解决办法: 添加
spring.sql.init.platform=mysql
到这,nacos 源码就下载了,还差 业务端的项目 启动,方便我们的debug
服务 注册
针对nacos 里管理的服务实例数据服务发现,注册(写操作), 存储(nacos集群存放服务实例数据),发现(读操作),针对临时服务实例数据的存储
注册的问题列表
- 服务注册找nacos 集群里哪个节点来发起?
随机 - 服务实例数据 是存储在哪个nacos节点
- 发现的时候 找哪个nacos?
- 怎么对比数据是否不一致?
注册的细节
首先,我们想确定 服务注册的问题 ,获得答案,我们还要知道 注册的入口在哪,可以先把 断点 放到 InstanceController 类的 register 方法中,至于前面的 springboot 对 nacos client的 封装,我们后面章节再看,现在先 假设 client 已经 发送注册消息到register 方法中,我们看看 他干了什么?
首先 request 为
@CanDistro 干什么的?
看注释是 用于标识一个方法需要判断是否应该根据distro被重定向,需要的话 就是 代表 需要走 distro 协议
往回找,看谁引用了,可以看到 DistroFilter 类
判断method是否标注CanDistro,如果是而且distroMapper不负责该service则构建http请求然后将结果写回Filter;如果不需要重定向则继续filterChain.doFilter
服务注册找nacos 集群里哪个节点来发起?
随机,里面会根据 @CanDistro 注解 重定向到 指定的节点进行注册操作,这里面有一个点,怎么选择 应该到哪个nacos 节点操作呢?
String localAddress = EnvUtil.getLocalAddress();
int index = servers.indexOf(localAddress);
int lastIndex = servers.lastIndexOf(localAddress);
if (lastIndex < 0 || index < 0) {
return true;
}
int target = distroHash(responsibleTag) % servers.size();
return target >= index && target <= lastIndex;
问题清单
- 数据库 可能换,当时设计的时候 怎么保证的扩展性
- CMDB 主要是基于 nacos 来是新 如果你的系统多机房里进行部署,基于cmdb 实现就近访问
- distro中 hash是怎么计算的? 请看mapSrv 方法
- nacos 在 2.2.0 中 提出的新特性 有一个是插件化 ,具体怎么实现的呢?