总文档 :文章目录
Github : github.com/black-ant
一 . 前言
水文一篇 , 哈哈哈哈哈哈~
文章目的 :
- 梳理 Nacos 创建功能的 Debug 方向
- 梳理 Nacos 组件的模块体系
文章大纲 : 该文档主要涉及以下几个主要的部分
- Nacos 服务发现
- Nacos 配置加载
- Nacos 健康检查
- Nacos 路由策略
PS : 文档参考来源为 官方文档 , 建议阅读文档了解快速使用
二 . 源码的编译
2.1 Nacos源码编译
1 | java复制代码// Step 1 : 下载源码 |
2.2 Nacos 源码运行
1 | java复制代码// Step 1 : 下载 Nacos 源码 |
三 . 模块源码
1 | xml复制代码<modules> |
3.1 Nacos 服务的发现和管理 (c0-c20)
Nacos 对服务的管理主要集中在 Naming 模块中 , 这里结合 Client 端看一下服务的发现和管理是什么逻辑 , 以及该如何去操作他们
3.1.1 控制台获取服务列表
外部接口 :
- C- CatalogController # listDetail : 获取服务详情列表
- C- CatalogController # instanceList: 列出特殊服务的实例
- C- CatalogController # serviceDetail : 服务详情
核心主要是通过 ServiceManager 进行处理 , 此处看一下内部相关的逻辑 :
1 | java复制代码通过三个接口不难发现 ,其最终的调用核心都是 ServiceManager 类 |
PS:C02_01 ConsistencyService 体系结构
当存在多个服务的时候 , 是如何存储的?
1 | java复制代码// 如上述图所示 , 相关的对象存放在 clusterMap 中 |
3.1.2 Nacos 服务和 Config 的控制类
1 | java复制代码Nacos 中主要通过 NamingService 和 ConfigService 对服务和配置进行控制 , 其底层原理仍然为 : , 这里来简单看一下 |
3.1.3 Nacos 的退出销毁
当我们注册的服务在关闭的时候 , Nacos 会在生命周期结束的时候从 Server 端注销该应用
Step 1 : Closeable 停止相关类 , 停止项目 , 当我们点击停止后 , 可以看到如下一串log
1 | java复制代码com.alibaba.nacos.client.naming : com.alibaba.nacos.client.naming.beat.BeatReactor do shutdown stop |
Step 2 : NacosServiceRegistry 注销
除了这里 Closeable 会关闭外 , 还会注销 Service , 此处主要是NacosServiceRegistry
1 | java复制代码public void deregister(Registration registration) { |
Nacos_Closeable 体系
3.1.4 健康检查流程
Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。
健康检查相关接口
- 发送实例心跳 (InstanceController) : /nacos/v1/ns/instance/beat
- 更新实例的健康状态 (HealthController) : /nacos/v1/ns/health/instance
Client 端发起心跳
服务端会定时发起心跳操作调用2个接口 :
1 | java复制代码C- BeatReactor |
服务端检测心跳
1 | java复制代码// 服务端同样会对实例进行检测 , 核心类为 ClientBeatCheckTask |
ACK 健康检查主要逻辑 ,同时推送信息
无意中发现了一个 ACK 机制 , 是通过事件出发的 . 这个模式看代码主要是为了在 Server 发生变化的时候 ,通过 udpClient , 以 UDP 端口推送更新
PS : 客户端在查询服务实例的时候,如果提供 udp 端口,则 server 会创建 udpClient
1 | java复制代码for (Instance instance : service.allIPs(Lists.newArrayList(clusterName))) { |
健康检查阈值的使用
在配置服务时 , 可以配置一个 0-1 的浮点数 , 定义健康检查的阈值 ,该阈值对应的类为 com.alibaba.nacos.api.naming.pojo.Service
1 | java复制代码C- Service |
但是阈值的目的是什么呢 ?
假设实例出现了大量的异常 , 那么就会导致最后压力会到那几个健康的实例上 , 这个时候 , 可能会出现连锁反应
为了避免这些情况 ,当达到健康阈值的时候 , 就将所有的实例返回.
这就是那句**ipMap.get(Boolean.TRUE).addAll(ipMap.get(Boolean.FALSE));**的目的.
虽然Client 端可能碰到异常实例 ,但是可以避免整个系统崩溃
/nacos/v1/ns/health/instance 参数
名称 | 类型 | 是否必选 | 描述 |
---|---|---|---|
namespaceId | 字符串 | 否 | 命名空间ID |
serviceName | 字符串 | 是 | 服务名 |
groupName | 字符串 | 否 | 分组名 |
clusterName | 字符串 | 否 | 集群名 |
ip | 字符串 | 是 | 服务实例IP |
port | int | 是 | 服务实例port |
healthy | boolean | 是 | 是否健康 |
权重的处理
权重主要是 Instance 对象中进行配置
1 | java复制代码C- Instance |
PS : 权重可以用于 Client 端时进行 权重分配处理
参考原文 @ blog.csdn.net/krisdad/art…
1 | java复制代码public class NacosWeightLoadBalanceRule extends AbstractLoadBalancerRule { |
其他要点
1 | java复制代码// Nacos 的默认值 |
3.2 Nacos 配置流程 C30-C60
3.2.1 Nacos 配置的管理
1 | java复制代码// 获取配置 , 这里主要有几个步骤 : |
LocalConfigInfoProcessor 主要逻辑
1 | JAVA复制代码// 这里本地配置是指本地 File 文件 , 这里通过源码推断一下使用的方式 : |
Pro 1 : 从这个源码里面 , 可以看到哪些知识点 ?
既然存在本地文件 , 是否意味着我可以通过修改这个路径优先使用本地配置 , 此处修改以下路径后测试成功
省略\nacos\config\fixed-127.0.0.1_8848_nacos\data\config-data\one1\test1
1 | java复制代码PS : 除了这个路径 , SpringBoot 运行在配置文件中直接配置路径 -> |
Pro 2 : Filter 的使用
上面可以看到 , 配置的处理中 , 都有个默认的 Filter 处理
configFilterChainManager.doFilter(null, cr);
1 | java复制代码 // 依照这个逻辑 , 是可以进行更多配置的 |
TODO : 此处如何植入 Filter 待完善 , 没找到接口添加Filter , 奇怪….
3.2.2 Nacos 配置的容灾处理
Nacos LocalConfigInfoProcessor 提供了容灾的功能 , 方式包含2种 : 本地配置和快照处理
本地配置
上面说了 , 修改指定路径即可实现
配置快照
Nacos 的客户端 SDK 会在本地生成配置的快照。当客户端无法连接到 Nacos Server 时,可以使用配置快照显示系统的整体容灾能力。配置快照类似于 Git 中的本地 commit,也类似于缓存,会在适当的时机更新,但是并没有缓存过期(expiration)的概念。
3.2.3 Nacos 动态配置处理
动态配置主要是指配置变更时的监听 :
Nacos 通过长轮询检测配置是否变化 , 对应的核心类为 LongPollingRunnable # checkUpdateDataIds , 对这里 Debug 看下 >>>>
1 | java复制代码 |
3.2.4 Nacos 元数据
这里来看一下 , Nacos 的元数据是什么 ?
Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。
1 | java复制代码// 方式一 : 配置服务的时候配置 |
3.3 Nacos 负载均衡
Nacos 的负载均衡归属于 动态 DNS 服务
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。
基于 Feign 相关的知识 , 我们知道 , Balance 的处理是在 BaseLoadBalancer 中结合 Rule 处理的 , 这里我们来分析一下 , 2 者是通过什么结构进行连接处理的
Step 1 : Feign 对 Nacos 的调用
我们以 BaseLoadBalancer 为起点 , 进行 Debug 处理 , 来到点位 PredicateBasedRule
1 | java复制代码C- PredicateBasedRule |
3.4 集群的处理
Nacos 集群使用
Nacos 的集群使用比较简单 , 只需要在 /conf/cluster.conf 中配置对应的服务信息即可>>>>
1 | java复制代码 |
Nacos 集群源码跟踪
来看一下源码层面 , 这个逻辑是怎么处理的 ?
核心处理类在 com.alibaba.nacos.core.cluster
1 | java复制代码 |
总结
这篇文章又是一篇更偏向于应用的文章 , 源码深入的较少 , 更重要的原因是因为 Nacos 的源码分层更清楚 , 结构清晰 , 不需要太负载的深入.
另外 , Nacos 2.0 也在发布中 , 看文档采用了 Socket 长连接的方式 , 后续如果有机会 , 对比一下2者的区别看看.
附录
# 附录一 : 手动调用 Server
1 | java复制代码package com.alibaba.nacos.discovery.service; |
# 附录二 : 手动调用 Config
1 | java复制代码public class NacosClientConfigService implements ApplicationRunner { |
# 附录三 : 使用NacosInjected
可以通过 的
1 | java复制代码<!-- 使用 Nacos Inject --> |
# 附录四 : Naocs 官方架构图 (搬运)
这里是纯搬运 , 可以看官方文档 @ nacos.io/zh-cn/docs/…
功能图 :
- 服务管理:实现服务CRUD,域名CRUD,服务健康状态检查,服务权重管理等功能
- 配置管理:实现配置管CRUD,版本管理,灰度管理,监听管理,推送轨迹,聚合数据等功能
- 元数据管理:提供元数据CURD 和打标能力
- 插件机制:实现三个模块可分可合能力,实现扩展点SPI机制
- 事件机制:实现异步化事件通知,sdk数据变化异步通知等逻辑
- 日志模块:管理日志分类,日志级别,日志可移植性(尤其避免冲突),日志格式,异常码+帮助文档
- 回调机制:sdk通知数据,通过统一的模式回调用户处理。接口和数据结构需要具备可扩展性
- 寻址模式:解决ip,域名,nameserver、广播等多种寻址模式,需要可扩展
- 推送通道:解决server与存储、server间、server与sdk间推送性能问题
- 容量管理:管理每个租户,分组下的容量,防止存储被写爆,影响服务可用性
- 流量管理:按照租户,分组等多个维度对请求频率,长链接个数,报文大小,请求流控进行控制
- 缓存机制:容灾目录,本地缓存,server缓存机制。容灾目录使用需要工具
- 启动模式:按照单机模式,配置模式,服务模式,dns模式,或者all模式,启动不同的程序+UI
- 一致性协议:解决不同数据,不同一致性要求情况下,不同一致性机制
- 存储模块:解决数据持久化、非持久化存储,解决数据分片问题
- Nameserver:解决namespace到clusterid的路由问题,解决用户环境与nacos物理环境映射问题
- CMDB:解决元数据存储,与三方cmdb系统对接问题,解决应用,人,资源关系
- Metrics:暴露标准metrics数据,方便与三方监控系统打通
- Trace:暴露标准trace,方便与SLA系统打通,日志白平化,推送轨迹等能力,并且可以和计量计费系统打通
- 接入管理:相当于阿里云开通服务,分配身份、容量、权限过程
- 用户管理:解决用户管理,登录,sso等问题
- 权限管理:解决身份识别,访问控制,角色管理等问题
- 审计系统:扩展接口方便与不同公司审计系统打通
- 通知系统:核心数据变更,或者操作,方便通过SMS系统打通,通知到对应人数据变更
- OpenAPI:暴露标准Rest风格HTTP接口,简单易用,方便多语言集成
- Console:易用控制台,做服务管理、配置管理等操作
- SDK:多语言sdk
- Agent:dns-f类似模式,或者与mesh等方案集成
- CLI:命令行对产品进行轻量化管理,像git一样好用
领域模型 :
SDK 类图 :
本文转载自: 掘金