图文解析 Nacos 配置中心的实现
目录
一、什么是 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
作为配置中心的源码实现,包含了客户端和服务端两部分,内容基本覆盖了配置中心功能的关键点,既作为学习总结,也希望对阅读的朋友有所帮助。
相关文章:

图文解析 Nacos 配置中心的实现
目录 一、什么是 Nacos 二、配置中心的架构 三、Nacos 使用示例 (一)官方代码示例 (二)Properties 解读 (三)配置项的层级设计 (四)获取配置 (五)注册…...
P1918 保龄球
Portal. 记录每一个瓶子数对应的位置即可。 注意到值域很大( a i ≤ 1 0 9 a_i\leq 10^9 ai≤109),要用 map 存储。 #include <bits/stdc.h> using namespace std;map<int,int> p;int main() {int n;cin>>n;for(int i…...

SAP-PP-报错:工作中心 7333_JQ 工厂 7331 对任务清单类型 N 不存在
创建工艺路线时报错:工作中心 7333_JQ 工厂 7331 对任务清单类型 N 不存在, 这是因为在创建工作中心时未维护控制键值导致的...

MySQL -- 用户管理
MySQL – 用户管理 文章目录 MySQL -- 用户管理一、用户1.用户信息2.创建用户3.删除用户4.远端登录MySQL5.修改用户密码6.数据库的权限 一、用户 1.用户信息 MySQL中的用户,都存储在系统数据库mysql的user表中: host: 表示这个用户可以从…...
IOS浏览器不支持对element ui table的宽度设置百分比
IOS浏览器不支持对element ui table的宽度设置百分比 IOS浏览器会把百分号识别成px,所以我们可以根据屏幕宽度将百分比转换成px getColumnWidth(data) {const screenWidth window.innerWidth;const desiredPercentage data;const widthInPixels (screenWidth *…...

Vue+OpenLayers 创建地图并显示鼠标所在经纬度
1、效果 2、创建地图 本文用的是高德地图 页面 <div class"map" id"map"></div><div id"mouse-position" class"position_coordinate"></div>初始化地图 var gaodeLayer new TileLayer({title: "高德地…...
01-编码-H264编码原理
1.整体概念 编码的含义就是压缩,将摄像头采集的YUV或RGB数据压缩成H264。 压缩的过程就是去除信息冗余的过程,一般视频有如下的冗余信息。 (1)空间冗余:在同一个画面中,相邻的像素点之间的变化很小,因而可以用一个特定大小的矩阵来描述相邻的这些像素。 (2)时间冗余:…...

RxJava/RxAndroid的操作符使用(二)
文章目录 一、创建操作1、基本创建2、快速创建2.1 empty2.2 never2.3 error2.4 from2.5 just 3、定时与延时创建操作3.1 defer3.2 timer3.3 interval3.4 intervalRange3.5 range3.6 repeat 二、过滤操作1、skip/skipLast2、debounce3、distinct——去重4、elementAt——获取指定…...

【C语法学习】20 - 文件访问顺序
文章目录 0 前言1 文件位置指示符2 rewind()函数2.1 函数原型2.2 参数2.3 返回值2.4 使用说明 3 ftell()函数3.1 函数原型3.2 参数3.3 返回值 4 fseek()函数4.1 函数原型4.2 参数4.3 返回值 5 示例5.1 示例15.2 示例2 0 前言 C语言文件访问分为顺序文件访问和随机文件访问。 …...

Etcd 常用命令与备份恢复
1. etcd简介 官方网站:etcd.io 官方文档:etcd.io/docs/v3.5/op-guide/maintenance 官方硬件推荐:etcd.io/docs/v3.5/op-guide/hardware github地址:github.com/etcd-io/etcd etcd是CoreOS团队于2013年6月发起的开源项目…...
获取任意时间段内周、季度、半年的二级联动
#需求是获取两个时间内 年周 、年季度、年半年的二级联动# 找了半天也找不到什么有用的信息 就自己简单写了一个 思路是先获取年的列表再去嵌套查询 根据前端VUE提供的格式嵌套 public function getDate(){$leixing Request::param(leixing);$larr array(1,2,3,4);if(empty(…...

前端面试系列之工程化篇
如果对前端八股文感兴趣,可以留意公重号:码农补给站,总有你要的干货。 前端工程化 Webpack 概念 本质上,webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个…...

京东按关键词搜索商品列表接口:竞品分析,商品管理,营销策略制定
京东搜索商品列表接口是京东开放平台提供的一种API接口,通过调用该接口,开发者可以获取京东平台上商品的列表数据,包括商品的标题、价格、库存、月销量、总销量、详情描述、图片等信息。 接口的主要作用包括: 市场调研ÿ…...

Microsoft Dynamics 365 CE 扩展定制 - 9. Dynamics 365扩展
在本章中,我们将介绍以下内容: Dynamics 365应用程序Dynamics 365通用数据服务构建Dynamics 365 PowerApp使用Flow在CDS和Dynamics 365之间移动数据从AppSource安装解决方案使用数据导出服务解决方案进行数据复制从CRM数据构建Power BI仪表板简介 多年来,Dynamics CRM已从一…...

多篇论文介绍-Wiou
论文地址 目录 https://arxiv.org/pdf/2301.10051.pdf 01 CIEFRNet:面向高速公路的抛洒物检测算法 02改进 YOLOv5 的 PDC 钻头复合片缺损识别 03 基于SimAM注意力机制的DCN-YOLOv5水下目标检测 04 基于改进YOLOv7-tiny 算法的输电线路螺栓缺销检测 05 基于改…...
Django介绍,安装,创建
文章目录 1. web应用程序1.1 什么是web?1.2 web应用程序的优点1.3 web应用程序的缺点1.4 什么是web框架? 2. 手撸web框架 1. web应用程序 1.1 什么是web? Web应用程序是一种可以通过Web访问的应用程序,用户只需要有浏览器即可,不需要再安装其他软件 案…...
Java通过javacv获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息)
相信我们都会或多或少需要给前端返回视频或者音频的一些信息,那么今天这篇文章通过Java语言使用javacv来获取视频、音频、图片等元数据信息(分辨率、大小、帧等信息) 一、首先导入依赖 可以先导入javacv/javacv-platform依赖,由于依赖比较大,所以我们可以先去除部分不需…...
flask和fastapi的区别以及demo实现
flask和fastapi的区别以及demo实现 flask和fastapi的区别fastapi简单demoFastAPI包括全局异常捕捉和参数验证的demoflask和fastapi的区别 Flask:Flask是一个轻量级的Web框架,它提供了最基本的工具,可以自由选择其他库和组件来构建应用。灵活性:Flask允许用户自由选择数据库、…...

python特殊循环队列_队中元素个数代替队尾指针
对于循环队列来说,如果知道队头指针和队中元素个数,则可以计算出队尾指针。也就是说,可以用队中元素个数代替队尾指针。设计出这种循环队列的判队空、进队、出队和取队头元素的算法。 本例的循环队列包含data 数组、队头指针 front和队中元素…...

什么是观察者模式?用 Python 如何实现 Observer(观察者或发布订阅)对象行为型模式?
什么是观察者模式? 观察者模式(Observer pattern)是一种行为型设计模式,它允许对象之间建立一种一对多的依赖关系,当一个对象的状态发生变化时,其相关依赖对象都会得到通知并自动更新。 在观察者模式中&am…...

Pandas 技术解析:从数据结构到应用场景的深度探索
序 我最早用Python做大数据项目时,接触最早的就是Pandas了。觉得对于IT技术人员而言,它是可以属于多场景的存在,因为它的本身就是数据驱动的技术生态中,对于软件工程师而言,它是快速构建数据处理管道的基石࿱…...

【HarmonyOS Next之旅】DevEco Studio使用指南(三十一) -> 同步云端代码至DevEco Studio工程
目录 1 -> 同步云函数/云对象 1.1 -> 同步单个云函数/云对象 1.2 -> 批量同步云函数/云对象 2 -> 同步云数据库 2.1 -> 同步单个对象类型 2.2 -> 批量同步对象类型 3 -> 一键同步云侧代码 1 -> 同步云函数/云对象 说明 对于使用DevEco Studio…...

【读论文】U-Net: Convolutional Networks for Biomedical Image Segmentation 卷积神经网络
摘要1 Introduction2 Network Architecture3 Training3.1 Data Augmentation 4 Experiments5 Conclusion背景知识卷积激活函数池化上采样、上池化、反卷积softmax 归一化函数交叉熵损失 Olaf Ronneberger, Philipp Fischer, Thomas Brox Paper:https://arxiv.org/ab…...

pe文件结构(TLS)
TLS 什么是TLS? TLS是 Thread Local Storage 的缩写,线程局部存储。主要是为了解决多线程中变量同步的问题 如果需要要一个线程内部的各个函数调用都能访问,但其它线程不能访问的变量(被称为static memory local to a thread 线程局部静态变…...

如何使用Webhook触发器,在 ONLYOFFICE 协作空间构建智能工作流
在数字化办公中,ONLYOFFICE 协作空间作为一款功能强大的文档协作平台,提供了丰富的自动化功能。对于开发者而言,Webhook 触发器是实现业务流程自动化与系统集成的关键工具。本文将深入探讨如何在 ONLYOFFICE 协作空间中高效利用 Webhook&…...
STM32实战: CAN总线数据记录仪设计方案
以下是基于STM32的CAN总线数据记录仪/转发器的设计与实现方案,结合了核心功能和进阶需求: 系统架构 graph TBA[CAN总线] -->|CAN_H/CAN_L| B(STM32 bxCAN)B --> C[数据处理核心]C --> D[SD卡存储<br>FATFS文件系统]C --> E[串口输出…...

《PMBOK® 指南》第八版草案重大变革:6 大原则重构项目管理体系
项目管理领域的权威指南迎来关键升级!PMI 最新发布的《PMBOK 指南》第八版草案引发行业广泛关注,此次修订首次将项目管理原则浓缩为 6 大黄金法则,重构 7 大绩效域,并首度公开过程组与绩效域的映射关系。本文将全面解析新版核心变…...

深入理解 transforms.Normalize():PyTorch 图像预处理中的关键一步
深入理解 transforms.Normalize():PyTorch 图像预处理中的关键一步 在使用 PyTorch 进行图像分类、目标检测等深度学习任务时,我们常常会在数据预处理部分看到如下代码: python复制编辑transform transforms.Compose([transforms.ToTensor…...

黑龙江云前沿服务器租用:便捷高效的灵活之选
服务器租用,即企业直接从互联网数据中心(IDC)提供商处租赁服务器。企业只需按照所选的服务器配置和租赁期限,定期支付租金,即可使用服务器开展业务。 便捷快速部署:租用服务器能极大地缩短服务器搭建周期…...
HTTP 请求协议简单介绍
目录 常见的 HTTP 响应头字段 Java 示例代码:发送 HTTP 请求并处理响应 代码解释: 运行结果: 文件名: 总结: HTTP(HyperText Transfer Protocol)是用于客户端与服务器之间通信的协议。它定…...