营销网站制作哪家好,企业宣传画册制作,wordpress购物插件下载,百度热搜榜排名目录
一、什么是 Nacos
二、配置中心的架构
三、Nacos 使用示例
#xff08;一#xff09;官方代码示例
#xff08;二#xff09;Properties 解读
#xff08;三#xff09;配置项的层级设计
#xff08;四#xff09;获取配置
#xff08;五#xff09;注册…目录
一、什么是 Nacos
二、配置中心的架构
三、Nacos 使用示例
一官方代码示例
二Properties 解读
三配置项的层级设计
四获取配置
五注册监听器
六配置长轮询
四、Nacos 服务端解析
一配置 Dump
二配置注册
三处理长轮询
五、全文总结 一、什么是 Nacos
Nacos 是阿里发起的开源项目地址github.com/alibaba/nac…。Nacos 主要提供两种服务一是配置中心支持配置注册、变更下发、层级管理等意义是不停机就可以动态刷新服务内部的配置项二是作为命名服务提供服务的注册和发现功能通常用于在 RPC 框架的 Client 和 Server 中间充当媒介还附带有健康监测、负载均衡等功能。
本文聚焦于 Nacos 的第一块功能即配置中心的实现。先叙述一个配置中心通常需要哪些组成部分再结合 Nacos 1.1.4 的源码探究一下这些设计是如何反映在源码上的。
二、配置中心的架构
配置中心本身并不复杂前提是你先将 CAP 的取舍问题晾在一边的话。配置中心最基础的功能就是存储一个键值对用户发布一个配置configKey然后客户端获取这个配置项configValue进阶的功能就是当某个配置项发生变更时将变更告知客户端刷新旧值。
下方的架构图简要描述了一个配置中心的大致架构用户可以通过管理平台发布配置通过 HTTP 调用将配置注册到服务端服务端将之保存在 MySQL 等持久化存储引擎中用户通过客户端 SDK 访问服务端的配置同时建立 HTTP 的长轮询监听配置项变更同时为了减轻服务端压力和保证容灾特性配置项拉取到客户端之后会保存一份快照在本地文件中SDK 优先读取文件里的内容。
这里省略了许多细节问题例如配置分层设计权限校验客户端长轮询的间隔设置服务端每次查询都需要访问 MySQL 么配置变更是主动推送还是等定时轮询触发等还有就是运维高可用方面的工作私以为这个是配置中心的精华例如节点跨地域部署网络分区时配置如何保证可写可推送变更等。真正实现一个高质量的配置中心还是需要长时间打磨的。 三、Nacos 使用示例 下文涉及的源码均基于 Nacos 1.1.4 版本 一官方代码示例
先看一下官方文档中对于 Nacos 的 API 使用的示例代码第一步是传递配置新建 ConfigService 实例第二步可以通过相应的接口获取配置和注册配置监听器。使用方式非常简单易懂不再赘述。
try {// 传递配置String serverAddr {serverAddr};String dataId {dataId};String group {group};Properties properties new Properties();properties.put(serverAddr, serverAddr);// 新建 configServiceConfigService configService NacosFactory.createConfigService(properties);String content configService.getConfig(dataId, group, 5000);System.out.println(content);// 注册监听器configService.addListener(dataId, group, new Listener() {Overridepublic void receiveConfigInfo(String configInfo) {System.out.println(recieve1: configInfo);}Overridepublic Executor getExecutor() {return null;}
});
} catch (NacosException e) {// TODO -generated catch blocke.printStackTrace();
}二Properties 解读
serverAddr 传递的是配置中心服务端的地址列表被内部名为 ServerListManager 的类解析成地址列表进行管理进行 HTTP 调用时会从中选择存活的机器拼接成 URL 完成调用一旦在调用时该地址抛异常则客户端会有一些处理措施例如转换下次选择的节点等。值得注意的是通常在实践中不会采取这种硬编码的方式可以将其配置在 Zookeeper 或者注册发现中心上在启动时动态拉取。
三配置项的层级设计
Nacos 官方给出了这样的设计图 dataId 可以理解为用户自定义的配置健group 可以理解为配置分组名称这个属于配置层级设计的概念。简单来说配置中心会通过层次设计来支持不同的分区以此区分不同的环境、不同的分组、甚至不同的开发者满足在开发过程中灰度发布、测试等需求。因此怎样设计都可以只要有含义就好例如下图也不是不可以。 Nacos 客户端解析
四获取配置
获取配置的主要方法是 NacosConfigService 类的 getConfigInner 方法通常情况下该方法直接从本地文件中取得配置的值如果本地文件不存在或者内容为空则再通过 HTTP GET 方法从远端拉取配置并保存到本地快照中。 当通过 HTTP 获取远端配置时Nacos 提供了两种熔断策略一是超时时间二是最大重试次数默认重试三次。
五注册监听器
配置中心客户端对某个配置项注册监听器是很常见的需求达到在配置项变更的时候执行回调的功能。
iconfig.addListener(dataId, group, ml);
iconfig.getConfigAndSignListener(dataId, group, 1000, ml);
Nacos 可以通过以上方式注册监听器它们内部的实现均是调用 ClientWorker 类的 addCacheDataIfAbsent。其中 CacheData 是一个维护配置项和其下注册的所有监听器的实例私以为这个名字取得并不好不容易理解。
所有的 CacheData 都保存在 ClientWorker 类中的原子 cacheMap 中其内部的核心成员有 其中content 是配置内容MD5 值是用来检测配置是否发生变更的关键内部还维护着一个若干监听器组成的数组一旦发生变更则依次回调这些监听器。
六配置长轮询
ClientWorker 通过其下的两个线程池完成配置长轮询的工作一个是单线程的 executor每隔 10ms 按照每 3000 个配置项为一批次捞取待轮询的 cacheData 实例将其包装成为一个 LongPollingTask 提交进入第二个线程池 executorService 处理。 该长轮询任务内部主要分为四步
检查本地配置忽略本地快照不存在的配置项检查是否存在需要回调监听器的配置项如果本地没有配置项的从服务端拿返回配置内容发生变更的键值列表每个键值再到服务端获取最新配置更新本地快照补全之前缺失的配置检查 MD5 标签是否一致不一致需要回调监听器
如果该轮询任务抛出异常等待一段时间再开始下一次调用减轻服务端压力。另外Nacos 在 HTTP 工具类中也有限流器的代码通过多种手段降低轮询或者大流量情况下的风险。下文还会讲到如果在服务端没有发现变更的键值那么服务端会夯住这个 HTTP 请求一段时间客户端侧默认传递的超时是 30s以此进一步减轻客户端的轮询频率和服务端的压力。
四、Nacos 服务端解析
一配置 Dump
服务端启动时就会依赖 DumpService 的 init 方法从数据库中 load 配置存储在本地磁盘上并将一些重要的元信息例如 MD5 值缓存在内存中。服务端会根据心跳文件中保存的最后一次心跳时间来判断到底是从数据库 dump 全量配置数据还是部分增量配置数据如果机器上次心跳间隔是 6h 以内的话。
全量 dump 当然先清空磁盘缓存然后根据主键 ID 每次捞取一千条配置刷进磁盘和内存。增量 dump 就是捞取最近六小时的新增配置包括更新的和删除的先按照这批数据刷新一遍内存和文件再根据内存里所有的数据全量去比对一遍数据库如果有改变的再同步一次相比于全量 dump 的话会减少一定的数据库 IO 和磁盘 IO 次数。
二配置注册
Nacos 服务端是一个 SpringBoot 实现的服务注册配置主要代码位于 ConfigController 和 ConfigServletInner 中。服务端一般是多节点部署的集群因此请求一开始只会打到一台机器这台机器将配置插入 MySQL 中进行持久化这部分代码很简单不再赘述。
因为服务端并不是针对每次配置查询都去访问 MySQL 的而是会依赖 dump 功能在本地文件中将配置缓存起来。因此当单台机器保存完毕配置之后需要通知其他机器刷新内存和本地磁盘中的文件内容因此它会发布一个名为 ConfigDataChangeEvent 的事件这个事件会通过 HTTP 调用通知所有集群节点包括自身触发本地文件和内存的刷新。 三处理长轮询
上文提到客户端会有一个长轮询任务拉取服务端的配置变更那么服务端是如何处理这个长轮询任务的呢源码逻辑位于 LongPollingService 类其中有一个 Runnable 任务名为 ClientLongPolling服务端会将受到的轮询请求包装成一个 ClientLongPolling 任务该任务持有一个 AsyncContext 响应对象Servlet 3.0 的新机制通过定时线程池延后 29.5s 执行。 为什么比客户端 30s 的超时时间提前 500ms 返回是为了最大程度上保证客户端不会因为网络延时造成超时 这里需要注意的是在 ClientLongPolling 任务被提交进入线程池待执行的同时服务端也通过一个队列 allSubs 保存了所有正在被夯住的轮询请求这是因为在配置项被夯住的期间内如果用户通过管理平台操作了配置项变更、或者服务端该节点收到了来自其他节点的 dump 刷新通知那么都应立即取消夯住的任务及时通知客户端数据发生了变更。
为了达到这个目的LongPollingService 类继承自 Event 接口实际上本身是个事件触发器需要实现 onEvent 方法其事件类型是 LocalDataChangeEvent。
当服务端在请求被夯住的期间接收到某项配置变更时就会发布一个 LocalDataChangeEvent 类型的事件通知注意同上文中的 ConfigDataChangeEvent 区别之后会将这个变更包装成一个 DataChangeTask 异步执行内容就是从 allSubs 中找出夯住的 ClientLongPolling 请求写入变更强制其立即返回。
因此完整的流程如下如果非接收请求的节点那么忽略第一步持久化配置后开始 五、全文总结
本文聚焦于 Nacos 作为配置中心的源码实现包含了客户端和服务端两部分内容基本覆盖了配置中心功能的关键点既作为学习总结也希望对阅读的朋友有所帮助。